Counting negative values in list
I assume that you have numeric values. A much more efficient way would be
-Total[UnitStep[data] - 1]]
or
Total[1-UnitStep[data]]
Note: While the second notation is certainly a bit more compact, it is about 35% slower than the double-minus notation. I have no idea why. On my system, it takes on average 0.22 sec vs 0.30 sec.
Compare timings between the faster UnitStep version and the pattern matching approach:
data = RandomReal[{-10, 10}, 10^7];
Timing[-Total[UnitStep[data] - 1]]
(* ==> {0.222, 5001715} *)
Timing[Count[data, _?Negative]]
(* ==> {6.734, 5001715} *)
Use _?Negative
:
list = RandomInteger[{-9, 9}, 30]
Count[list, _?Negative]
Your pattern will match an object with an explicit negative sign:
Count[{a, -b, c, a, -a, a, -b}, -_]
3
You could combine the patterns to match either:
Count[{-1, -2, 3, 4, -a, b, -c}, -_ | _?Negative]
4
Since this has become a speed competition (which is fine by me), rather than the beginner's question I took it to be, here is my own variation, using Tr
for fast packed array summing:
neg = Length@# - Tr@UnitStep@# &;
Timings:
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] := Do[
If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}],
{i, 0, 15}
]
list = RandomInteger[1*^7 {-1, 1}, 1*^8];
-Total[UnitStep[list] - 1] // timeAvg
Length[list] - Total[UnitStep[list]] // timeAvg
neg @ list // timeAvg
0.592
0.234
0.1278
For numeric values, the following:
Length[data] - Total[UnitStep[data]]
is 50% faster than Thomas' solution.
Update: An even faster approach will be to compile to C, as shown in the following function f
:
ClearAll[f];
f = Compile[{{vector, _Real, 1}, {bound, _Real}},
Module[{t = 0, i = 1, len = Length[vector]},
For[i = 1, i <= len, i++, t += Boole[vector[[i]] < bound]]; t],
CompilationTarget -> "C", "RuntimeOptions" -> "Speed"]
Using the timeAvg function, as defined in Mr. Wizard's answer, we have:
SetAttributes[timeAvg, HoldFirst]
timeAvg[func_] :=
Do[If[# > 0.3, Return[#/5^i]] & @@ Timing@Do[func, {5^i}], {i, 0,
15}];
data = RandomReal[{-10, 10}, 10^7];
{-Total[UnitStep[data] - 1] // timeAvg,
Length[data] - Total[UnitStep[data]] // timeAvg,
Length[data] - Tr[UnitStep[data]] // timeAvg,
f[data, 0.] // timeAvg}
(* ==> {0.105993, 0.0431972, 0.0422639, 0.0141324} *)
Note that the function f
defined above will work for any upper bound, and not just 0. And would be significantly faster (at least in my machine) than the corresponding Length[data]- Tr[UnitStep[data - bound]]
approach when bound
is not zero.
For the dangers with the use of "RuntimeOptions"->"Speed"
, see the Mathematica help: RuntimeOptions.