`Count` for `SparseArray`
I can't speak to why exactly it doesn't work, but as for a workaround...
If you want to simply count how many values are unspecified, you can take the product of the dimensions (to get the hypothetical number of elements) and then subtract off the number of specifications (note that one specification is the default one, so we must subtract 1):
(* s is a SparseArray *)
(* Counting number of default values: *)
Times @@ Dimensions[s] - (Length[ArrayRules[s]] - 1)
If you want to count how many elements of a given form x
that s
has, but only among specified elements, you can use
(* Counting x's among non-default values: *)
Count[ Values[Most @ ArrayRules[s]], x]
Since SparseArray
s always subsume specified values that happen to be the same as the default value into the default value (e.g. ArrayRules[SparseArray[{1 -> 5, 2 -> 0, 10 -> 256}]]
gives {1 -> 5, 10 -> 256}
), and since the last element of ArrayRules
is always the default rule {_, _, ...} -> def
, we can package this into a function which checks if the number we're counting is the default value of our sparse array or not, and then does one of the two above accordingly.
SparseCount[s_, x_] := Module[{values = Values[ArrayRules[s]]},
If[MatchQ[Last[values],x],
Times @@ Dimensions[s] - (Length[values] - 1),
Count[values,x]
]]
(Note that we no longer need the Most
, since if x
were going to match the default value, it would have been caught by the If
condition.)
Hope this helps!
saCount[s_SparseArray, a_] := Block[{v = s["NonzeroValues"] },
Count[v, a] + If[a == s["Background"], Times @@ Dimensions[s] - Length@v, 0]]
saCount[a, 0]
10
Timings:
sa = SparseArray[Table[{2^i, 3^i + i, i^5} -> 1, {i, 10}]]
saCount[sa, 0] // RepeatedTiming
{6.5*10^-6, 6047641599990}
SparseCount[sa, 0] // RepeatedTiming (* from thorimur's answer *)
{0.000018, 6047641599990}
sparseCount[sa, 0] // RepeatedTiming (* from OP *)
{8.*10^-6, 1014}