4
$\begingroup$

How do you find the number of elements in a matrix that are non-zero. For instance, the following matrix has 5 nonzero elements.

{0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1}
$\endgroup$
7
  • 5
    $\begingroup$ That is not correct Mathematica syntax ... $\endgroup$ Dec 10, 2013 at 17:15
  • 1
    $\begingroup$ Look up Position, Count, Cases and related functions. $\endgroup$
    – Yves Klett
    Dec 10, 2013 at 17:27
  • 1
    $\begingroup$ Two different ways: Position[{1, 0, 0, 1}, Except[0]?NumericQ, {1}] and SparseArray[{1, 0, 0, 1}]["NonzeroPositions"]. $\endgroup$
    – C. E.
    Dec 10, 2013 at 17:32
  • $\begingroup$ I think that @anon has sufficiently interesting answers in comments that this question might be worth fixing and keeping? $\endgroup$
    – Verbeia
    Dec 10, 2013 at 19:46
  • $\begingroup$ @Verbeia the question is still ambiguous. Not sure if it is about counting or finding non-zero elements. $\endgroup$
    – Yves Klett
    Dec 10, 2013 at 20:47

3 Answers 3

11
$\begingroup$

One can use Unitize and Total. Fast on packed arrays.

SeedRandom[1];
foo = RandomInteger[{0, 2}, 10^6] RandomInteger[{0, 2}, 10^6];

Total @ Unitize @ foo
(* 444089 *)

Total @ Unitize @ foo // timeAvg
(* 0.00950128 *)

Some comparisons:

Length @ SparseArray[foo]["NonzeroPositions"] // timeAvg
(* 0.0154271 *)

Length[foo] - Count[foo, 0] // timeAvg
(* 0.0440302 *)

Count[foo, x_ /; x != 0] // timeAvg
(* 0.358267 *)

Length[Select[foo, # != 0 &]] // timeAvg
(* 0.439782 *)

Timing function:

SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := 
 Do[If[# > 0.3, Return[#/5^i]] & @@ AbsoluteTiming@Do[func, {5^i}], {i, 0, 15}]
$\endgroup$
5
  • $\begingroup$ If the non zero elements are always 1s, you can spare the Unitize, or even use Lenght[lst]-Plus@@lst. How much faster would that be? $\endgroup$
    – Peltio
    Dec 16, 2013 at 0:52
  • 1
    $\begingroup$ If the nonzero entries were all 1, then Total@foo takes 0.00749397 sec. Plus @@ foo takes 0.092115 sec. because Apply (@@) unpacks the array. (foo = RandomInteger[{0, 1}, 10^6] RandomInteger[{0, 1}, 10^6]) $\endgroup$
    – Michael E2
    Dec 16, 2013 at 0:56
  • $\begingroup$ Darn packed arrays! There was no such thing when I learned Mathematica, last century! $\endgroup$
    – Peltio
    Dec 16, 2013 at 1:01
  • $\begingroup$ @Peltio AFAIK they were introduced in version 4 around 1999. $\endgroup$
    – Szabolcs
    Dec 16, 2013 at 1:38
  • $\begingroup$ @Szabolcs I was talking of the other 98 years of that century. :-) $\endgroup$
    – Peltio
    Dec 16, 2013 at 5:27
4
$\begingroup$

Very straightforward

Count[{0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1}, 
 x_ /; x != 0]
$\endgroup$
1
$\begingroup$

One way is to select the nonzero entries and then count how many there are:

lst = {0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1};
Length[Select[lst, # != 0 &]]
5
$\endgroup$

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.