I'm trying to compute the discrete histogram of a set of values.

By histogram I mean the absolute frequency a value appears on the dataset, by discrete I mean the values are from a discrete set, e.g. integers.

Example: given data = {1,4,1,2,3,1,4}, I would like to have an efficient way of obtaining something like

{{1,3}, {2,1}, {3,1}, {4,2}}

I Tried using BinCount and HistogramList, but both are more suitable for continuous values.

My current solution is to use Count along with DeleteDuplicates:

{#, Count[data, #]} & /@ DeleteDuplicates[data]

My question is: do you know any more efficient way (without using procedural programming)?

I ask this because if there are N elements from which M are distinct, this approach requires M sweeps on a dataset of size N (M calls of Count), which is not required for the outcome I'm searching for: this operation should be feasible in one sweep.


I believe you are looking for Tally.

data = {1, 4, 1, 2, 3, 1, 4};

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

As you can see from the timings, Tally is vastly superior. I believe this will be the case regardless what form the data takes.

data = RandomChoice[Range[10], 10^7];

AbsoluteTiming[r1 = {#, Count[data, #]} & /@ DeleteDuplicates[data];]
(* {4.321247, Null} *)

AbsoluteTiming[r2 = Tally[data];]
(* {0.017001, Null} *)

r1 == r2
  • $\begingroup$ That was exactly the function I was searching. The name couldn't be more easy to find... anyway, thank you, very useful answer. $\endgroup$ Aug 21 '13 at 16:18

Not the answer you're looking for? Browse other questions tagged or ask your own question.