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.