6

In the following matrix m every 0 should be replaced with a 1:

m = {{0,1,2},{5,0,3},{8,0,0}}

Desired result:

m' = {{1,1,2},{5,1,3},{8,1,1}}

What is the fastest way to do this for a matrix with 200-1000 elements?

Danvil
  • 1,505
  • 1
  • 10
  • 17

5 Answers5

13
m + 1 - Unitize[m]

might be faster because it preserves packed arrays, but we'd need a real test.

bill s
  • 68,936
  • 4
  • 101
  • 191
6

Just for fun: the following hack is even slightly faster than the solution using Unitize and vectorization, on really large matrices:

replaceZeros[m_?MatrixQ] := 
   Normal[
      SparseArray[m] /. HoldPattern[SparseArray[s___]] :>
          Module[{parts = {s}},
            parts[[3]] = 1;
            SparseArray @@ parts
          ]
   ];

but, in this forms at least, it explicitly uses the fact that elements being replaced are zeros. This is just for fun, in any case.

Leonid Shifrin
  • 114,335
  • 15
  • 329
  • 420
  • Unitize is twice as fast on my PC for 10^7 element matrix. – RunnyKine Oct 24 '13 at 15:36
  • @RunnyKine I used also 10^7 elements, and on my machine (Mac OS X 10.7.5 64 bit), Unitize is about 10-20 % slower. Which version of Mathematica you used? – Leonid Shifrin Oct 24 '13 at 15:40
  • Perhaps you 2 used different proportion of zeros? If lots of zeros probably Leonid's wins, and viceversa – Rojo Oct 24 '13 at 15:46
  • I'm using V9.0.1 Windows 8.1 64bit – RunnyKine Oct 24 '13 at 15:46
  • @Rojo Yes, I already noticed that too. But even if the zeros are very scarce, on my machine my code then is just the same speed as the one with Unitize. – Leonid Shifrin Oct 24 '13 at 15:47
  • @RunnyKine Well, I am using a different M version - this could be the reason for the difference, apart from a different platform. – Leonid Shifrin Oct 24 '13 at 15:48
  • I suppose, since I've tried different generation of the matrix (even limiting the Random generator to only 0 and 1) and every time, Unitize is at least twice as fast on my machine. – RunnyKine Oct 24 '13 at 15:50
  • If the element to be replaced were a common element, then I don't see why it would kill the speed advantage. Just change the common element using SparseArray[m, Automatic, toBeReplaced], instead. – rcollyer Oct 24 '13 at 16:35
  • @rcollyer Yes, you are right, and I was wrong. Still, this is a hack, because it uses the implementation details of SparseArray to achieve its goals. But I like it. – Leonid Shifrin Oct 24 '13 at 16:41
  • Dangit, I wanted to post this. +1 :-) – Mr.Wizard Oct 24 '13 at 19:12
  • Hack, yes. Useful, yes. +1 – rcollyer Oct 24 '13 at 22:29
4
m = {{0, 1, 2}, {5, 0, 3}, {8, 0, 0}} /. 0 -> 1
{{1, 1, 2}, {5, 1, 3}, {8, 1, 1}}

It's certainly the fastest to write down.

bill s
  • 68,936
  • 4
  • 101
  • 191
3
Replace[m, 0 -> 1, Infinity]

{{1, 1, 2}, {5, 1, 3}, {8, 1, 1}}

RunnyKine
  • 33,088
  • 3
  • 109
  • 176
0
{{0, 1, 2}, {5, 0, 3}, {8, 0, 0}} //. {a___, 0, b___} -> {a, 1, b}

{{1, 1, 2}, {5, 1, 3}, {8, 1, 1}}

For,

RandomInteger[0, {100000, 3}] //. {a___, 0, b___} -> {a, 1, b};

2.62 Sec

Pankaj Sejwal
  • 2,063
  • 14
  • 23