# What is the fastest way to replace all zeros in a matrix?

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?

-

m + 1 - Unitize[m]

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

-
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.

-
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.

-
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}}

-
{{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

-
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