6
$\begingroup$

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?

$\endgroup$

5 Answers 5

13
$\begingroup$
m + 1 - Unitize[m]

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

$\endgroup$
5
  • $\begingroup$ You likely need Unitize in place of UnitStep. $\endgroup$ Commented Oct 24, 2013 at 15:09
  • $\begingroup$ This is wrong if the matrix contains negative integers. Like @LeonidShifrin said, Unitize is the correct function here. $\endgroup$
    – RunnyKine
    Commented Oct 24, 2013 at 15:10
  • $\begingroup$ @Leonid Shifrin and RunnyKine - thanks. Indeed, I was taking the example quite literally -- Unitize is more general and does handle negative numbers. $\endgroup$
    – bill s
    Commented Oct 24, 2013 at 15:13
  • $\begingroup$ It's definitely fast so +1. $\endgroup$
    – RunnyKine
    Commented Oct 24, 2013 at 15:16
  • $\begingroup$ For me this is the fastest $\endgroup$
    – Danvil
    Commented Oct 26, 2013 at 15:42
6
$\begingroup$

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.

$\endgroup$
11
  • $\begingroup$ Unitize is twice as fast on my PC for 10^7 element matrix. $\endgroup$
    – RunnyKine
    Commented Oct 24, 2013 at 15:36
  • $\begingroup$ @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? $\endgroup$ Commented Oct 24, 2013 at 15:40
  • $\begingroup$ Perhaps you 2 used different proportion of zeros? If lots of zeros probably Leonid's wins, and viceversa $\endgroup$
    – Rojo
    Commented Oct 24, 2013 at 15:46
  • $\begingroup$ I'm using V9.0.1 Windows 8.1 64bit $\endgroup$
    – RunnyKine
    Commented Oct 24, 2013 at 15:46
  • $\begingroup$ @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. $\endgroup$ Commented Oct 24, 2013 at 15:47
4
$\begingroup$
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.

$\endgroup$
3
  • $\begingroup$ Why //. instead of /.? $\endgroup$ Commented Oct 24, 2013 at 14:56
  • $\begingroup$ @Timothy Wofford -- habit, I guess. /. is shorter. Rojo -- habit again. I"m always nervous when a white space means something though, as in: /. 0->1 is OK but /.0->1 is not. $\endgroup$
    – bill s
    Commented Oct 24, 2013 at 14:58
  • $\begingroup$ For me /. is 25% faster than //. $\endgroup$
    – Danvil
    Commented Oct 24, 2013 at 15:02
3
$\begingroup$
Replace[m, 0 -> 1, Infinity]

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

$\endgroup$
0
$\begingroup$
{{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

$\endgroup$
2
  • $\begingroup$ Try with RandomInteger[{0, 5}, {10^7, 3}] $\endgroup$
    – RunnyKine
    Commented Oct 24, 2013 at 17:13
  • $\begingroup$ @RunnyKine : ya you seem to be right, upto 10^6 its taking 16 sec, after that sort of bottleneck. $\endgroup$ Commented Oct 24, 2013 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.