MathGroup Archive 2009

[Date Index] [Thread Index] [Author Index]

Search the Archive

Re: Two questions about modification of a matrix.


Assuming that you store your matrix in a variable <matr>, here is the code:


MapIndexed[If[Times @@ #2 > Length[matr], 0, #1] &, matr, {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] =

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

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]]];

My benchmarks indicate 3-fold speed - up on <largeTestMatr>, with respect to
a rule-based solution.


On Mon, Jun 22, 2009 at 1:22 AM, Mayasky <alix.zhang at> 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)

  • Prev by Date: Re: laptop recommendation to run mathematica fast?
  • Next by Date: Re: Needs[], BeginPackage[], filename
  • Previous by thread: Re: Two questions about modification of a matrix.
  • Next by thread: Re: Re: Two questions about modification of a matrix.