Re: Two questions about modification of a matrix.
- To: mathgroup at smc.vnet.net
- Subject: [mg101057] Re: [mg101041] Two questions about modification of a matrix.
- From: Leonid Shifrin <lshifr at gmail.com>
- Date: Tue, 23 Jun 2009 07:03:21 -0400 (EDT)
- References: <200906220822.EAA09140@smc.vnet.net>
Hi, Assuming that you store your matrix in a variable <matr>, here is the code: 1. MapIndexed[If[Times @@ #2 > Length[matr], 0, #1] &, matr, {2}] 2. matr /. _?Negative :> 0 As usual in Mathematica, in both cases above the original matrix has not been changed. Rather a new copy of the matrix is created as a result. If your matrix is large, you can implement the 1. much more efficiently. Here is the previous implementation: In[1] = nullify[matr_?MatrixQ] := MapIndexed[If[Times @@ #2 > Length[matr], 0, #1] &, matr, {2}] Here is an alternative one using SparseArrays: In[2] = nullifyFast[matr_?MatrixQ] := Normal[SparseArray[Thread[# -> Extract[matr, #]]]] &[ Flatten[Thread[{#, Range[IntegerPart[Length[matr]/#]]}] & /@ Range[Length[matr]], 1]]; Here is a test matrix: In[3] = largeTestMatr = RandomInteger[{-20, 20}, {400, 400}]; Compare performance: In[4] = (res1 = nullifyFast[largeTestMatr]); // Timing Out[4] = {0.03, Null} In[5] = (res2 = nullify[largeTestMatr]); // Timing Out[5] = {2.073, Null} In[6] = res1 == res2 Out[6] = true The solutions have such a dramatic difference in performance (for large matrices), since the condition i*j>N is very strong and we only need to keep a very small (comparing to a total number of matrix elements) subset of elements non - zero, and thus in the second solution we can utilize efficient built-in Mathematica facilities such as SparseArrays, while the first solution is very general and does not utilize the resulting matrix structure. For the second problem, probably the easiest way to speed up code in case of large matrices is to use Compile: nullifyNegativeCompiled = Compile[{{matr, _Real, 2}}, Module[{i = 1, j = 1, new = matr}, For[i = 1, i <= Length[matr], i++, For[j = 1, j <= Length[matr], j++, If[matr[[i, j]] < 0, new[[i, j]] = 0]]]; new]]; My benchmarks indicate 3-fold speed - up on <largeTestMatr>, with respect to a rule-based solution. Regards, Leonid On Mon, Jun 22, 2009 at 1:22 AM, Mayasky <alix.zhang at gmail.com> wrote: > Suppose there is a N*N matrix. > > 1. How can I change all elements that satisfy i*j>N to 0 ? (Here i, j > is position of this element, as in mat[[i,j]]) > > 2. How can I change all negative elements in that matrix to 0 ? > > I know a "for loop" can be used, I just wonder if there is any more > concise and beautiful ways. (I doubt Mathematica doesn't have a 'find' > function as in another system which conveniently returns indice of elements > that satisfy a certain condition) > >
- Follow-Ups:
- Re: Re: Two questions about modification of
- From: Carl Woll <carlw@wolfram.com>
- Re: Re: Two questions about modification of a matrix.
- From: Andrzej Kozlowski <akoz@mimuw.edu.pl>
- Re: Re: Two questions about modification of
- References:
- Two questions about modification of a matrix.
- From: Mayasky <alix.zhang@gmail.com>
- Two questions about modification of a matrix.