Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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?

share|improve this question

5 Answers 5

up vote 11 down vote accepted
m + 1 - Unitize[m]

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

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

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.

share|improve this answer
    
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
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.

share|improve this answer
    
Why //. instead of /.? –  Timothy Wofford Oct 24 '13 at 14:56
    
@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. –  bill s Oct 24 '13 at 14:58
    
For me /. is 25% faster than //. –  Danvil Oct 24 '13 at 15:02
Replace[m, 0 -> 1, Infinity]

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

share|improve this answer
{{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

share|improve this answer
    
Try with RandomInteger[{0, 5}, {10^7, 3}] –  RunnyKine Oct 24 '13 at 17:13
    
@RunnyKine : ya you seem to be right, upto 10^6 its taking 16 sec, after that sort of bottleneck. –  Rorschach Oct 24 '13 at 17:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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