# Counting the number of values in each interval

We have

SeedRandom; aRRay = Sort@RandomReal[1, 20]

(*{0.042467, 0.147432, 0.196935, 0.302397, 0.303466, 0.327691, 0.35578,
0.469596, 0.473433, 0.473735, 0.476401, 0.542707, 0.549238, 0.756142,
0.760802, 0.804339, 0.825788, 0.863324, 0.890815, 0.952522}*)


Please assume an interval containing 0.1. How can we calculate the numbers of elements of aRRay in each interval. For instants, in the above case we wish to have an array you can say nUm[k] which contains:

interval = 0.1;
(* For: [0,0.1)*)      nUm = 1;
(* For: [0.1,0.2)*)    nUm = 2;
(* For: [0.2,0.3)*)    nUm = 0;
(*[0.3,0.4)*)          nUm = 3;
(*[0.3,0.4)*)          nUm = 4;


BinCounts[aRRay, {0, 0.4, 0.1}]

• I was not familiar with this function. Amazing. – Inzo Babaria Aug 5 '17 at 2:56
• If we have a list: {0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9} Do you know how I construct another list containing pairs: {{0,1},{0.1,2},{0.2,0},{0.3,3}....} – Inzo Babaria Aug 5 '17 at 3:12
• I tried Transpose I think it works correctly!! – Inzo Babaria Aug 5 '17 at 3:15
HistogramList[aRRay, {0, .4, .1}][]


{1, 2, 0, 4}

This is slower than BinCounts for regularly spaced bins:

SeedRandom; aRRay = Sort@RandomReal[1, 1000000];
BinCounts[aRRay, {0, 1., .1}] // Timing


{1.093812, {99869, 99884, 100051, 100351, 99540, 99971, 99695, 99930, 100337, 100372}}

HistogramList[aRRay, {0, 1., .1}][] // Timing


{1.527600, {99869, 99884, 100051, 100351, 99540, 99971, 99695, 99930, 100337, 100372}}

Slightly faster for irregular bins:

bins = Flatten[{0, Sort[RandomReal[1, 50]], 1}];
BinCounts[aRRay, {bins}] // AbsoluteTiming // First


1.667586

HistogramList[aRRay, {bins}][] // AbsoluteTiming // First


1.606415

Edit: I apologise for the number of changes this post has been through.

You can do better than BinCounts and HistogramList, but only (it seems) if the range of elements of the list, and the bin widths are known in advance and can be hardwired (and much better if the list consists of Integers). But for binning lists of Reals where the range and bins are not always known in advance, it's probably best to stick with HistogramList or BinCounts.

If the intervals are always 0.1 and the list elements are always between 0 and 1 you can do:

SeedRandom; aRRay = Sort@RandomReal[{0, 1}, 20];

binlist = Table[0, 10];
binlist[[#]]++ & /@ (IntegerPart[10 aRRay] + 1);
binlist

(* {1, 2, 0, 4, 4, 2, 0, 2, 4, 1} *)


This will also Compile, which can be really handy for larger lists:

histbins1 = Compile[{{list, _Real, 1}},
Block[{binlist = Table[0, 10]},
Scan[binlist[[#]]++ &, Floor[10 list] + 1];
binlist
], CompilationTarget -> "C", RuntimeOptions -> "Speed"
];

SeedRandom; aRRay = Sort@RandomReal[{0, 1}, 10000000];
First@AbsoluteTiming[res1 = BinCounts[aRRay, 0.1]]
First@AbsoluteTiming[res2 = HistogramList[aRRay, {0.1}][]]
First@AbsoluteTiming[res3 = fasthist[aRRay]]
res1 == res2 == res3

(* 0.171328
0.231146
0.151686
True *)


So there's a small speed up, but the interval and range are hardwired.

To generalise this effectively to different ranges and bin widths, it's worth noting that if the list consists of Integers we can do much better than BinCounts or HistogramList, both of which seem to sacrifice speed with Integers for their generality:

inthistbins = Compile[{{list, _Integer, 1}, {minmax, _Integer, 1}},
Block[{binlist, len = minmax[] - minmax[] + 1,
offset = 1 - minmax[]},
binlist = Table[0, len];
binlist[[# + offset]]++ & /@ list;
binlist
], CompilationTarget -> "C", RuntimeOptions -> "Speed"
];

SeedRandom; aRRay = RandomInteger[1000, 1000000];
First@AbsoluteTiming[res1 = Rest@HistogramList[aRRay, {1}][];]
First@AbsoluteTiming[res2 = Rest@BinCounts[aRRay, {1}];]
First@AbsoluteTiming[res3 = inthistbins[aRRay, {0, 1000}];]
res1 == res2 == res3

(* 0.0589792
0.0127482
0.00230177
True *)


So an obvious thing to try is to convert the list to Integers and do an Integer binning function:

histbins2 =
Compile[{{list, _Real, 1}, {minmax, _Real, 1}, {nbins, _Integer, 0}},
Block[{binlist = Table[0, nbins],
intlist =
IntegerPart[
nbins (list - minmax[])/(minmax[] - minmax[])] + 1},
Scan[binlist[[#]]++ &, intlist];
binlist
], CompilationTarget -> "C", RuntimeOptions -> "Speed"
];

SeedRandom; aRRay = Sort@RandomReal[{0, 1}, 10000000]
First@AbsoluteTiming[res4 = histbins2[aRRay, {0, 1}, 10]]

(* 0.184703 *)


Which ultimately loses out to BinCounts and the hardwired histbins1... Unless someone can give a faster way to convert list to Integers than the one I've used here.