Re: Re: Two questions about modification of
- To: mathgroup at smc.vnet.net
- Subject: [mg101094] Re: [mg101057] Re: [mg101041] Two questions about modification of
- From: Carl Woll <carlw at wolfram.com>
- Date: Wed, 24 Jun 2009 06:29:18 -0400 (EDT)
- References: <200906220822.EAA09140@smc.vnet.net> <200906231103.HAA07999@smc.vnet.net>
Leonid Shifrin wrote: > 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. > A much simpler (and faster) solution is to use Clip: Clip[matrix, {0, Infinity}] Carl Woll Wolfram Research > 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) >> >> >> > > >
- References:
- Two questions about modification of a matrix.
- From: Mayasky <alix.zhang@gmail.com>
- Re: Two questions about modification of a matrix.
- From: Leonid Shifrin <lshifr@gmail.com>
- Two questions about modification of a matrix.