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.
Unitize
in place of UnitStep
.
$\endgroup$
Commented
Oct 24, 2013 at 15:09
Unitize
is the correct function here.
$\endgroup$
Commented
Oct 24, 2013 at 15:10
Unitize
is more general and does handle negative numbers.
$\endgroup$
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.
$\endgroup$
Commented
Oct 24, 2013 at 15:36
Unitize
is about 10-20 % slower. Which version of Mathematica you used?
$\endgroup$
Commented
Oct 24, 2013 at 15:40
Unitize
.
$\endgroup$
Commented
Oct 24, 2013 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.
/.
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$
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
RandomInteger[{0, 5}, {10^7, 3}]
$\endgroup$
Commented
Oct 24, 2013 at 17:13