33
$\begingroup$

So I wanted to create a Histogram with a custom number of bins. Luckily there is a simple function for this in the form of Histogram[data, n] where n specifies the number of bins. There is even an example of using it in the documentation:

data = RandomVariate[NormalDistribution[0, 1], 200];
Histogram[data, 5]

Problem is that this doesn't produce a Histogram with five bins but with seven bins:

Mathematica graphics

Histogram[data, 6]still gives seven bins:

Mathematica graphics

Histogram[data, 7] also gives seven bins:

Mathematica graphics

But Histogram[data, 10] gives thirteen bins:

Mathematica graphics

Now I am utterly confused. Is this a bug or have I misunderstood something completely? How would I go about producing a Histogram with five bins?

$\endgroup$
5
  • 1
    $\begingroup$ Hmmm... A list with a single element is the bin width, not an integer as I thought. I don't have mma with me right now to test it out, but I think there's an explanation for it. This seems too fundamental to have a bug $\endgroup$
    – rm -rf
    Commented Jun 30, 2012 at 17:01
  • 3
    $\begingroup$ This is a documentation bug, not the OP's fault! The documentation indeed says literally (first example under Scope): "Specify the number of bins to use"... $\endgroup$
    – Jens
    Commented Jun 30, 2012 at 17:01
  • 2
    $\begingroup$ In the example above the bins are either 1 or 1/2 wide so I suspect that Mathematica adjusts the number of bins in order to get "nice" widths similar to for example FindDivisions. $\endgroup$
    – Heike
    Commented Jun 30, 2012 at 18:08
  • 2
    $\begingroup$ This is a great question, still relevant 4 years after its posting. Why has the documentation not changed? I've wasted a lot of time trying to figure what I've done wrong, only to realize 1) the documentation is wrong and 2) that's been known for a long time. $\endgroup$
    – GregH
    Commented Dec 2, 2016 at 13:46
  • $\begingroup$ Also note that Histogram might change the PlotRange and therefore does not show all bins. Use PlotRange -> All or PlotRange -> Full to see all bins. $\endgroup$
    – Qbyte
    Commented Feb 20, 2021 at 21:51

4 Answers 4

26
$\begingroup$

Under mma 8 you can use the undocumented {"Raw", n} bin specification to get exactly the number of bins you would like. Otherwise the bin widths and boundaries are chosen to be "nice" numbers.

Here is an example:

data = RandomVariate[NormalDistribution[0, 1], 200];
Histogram[data, {"Raw", 5}]

Example histogram

(I saw this first in a comment by Brett Champion to the answer here.)

$\endgroup$
4
  • $\begingroup$ Good memory! I forgot about that exchange (as did Sjoerd)... would've saved me some time trying to wade through the internals to see how it is implemented $\endgroup$
    – rm -rf
    Commented Jun 30, 2012 at 21:28
  • $\begingroup$ +1, good to know. Doesn't work on v.7 I confirm. $\endgroup$ Commented Jun 30, 2012 at 21:45
  • $\begingroup$ Works on 9.0.1.0. Thanks ! $\endgroup$
    – A.G.
    Commented Jan 27, 2015 at 22:02
  • $\begingroup$ Doesn't work in 10.4 :(. $\endgroup$ Commented Aug 5, 2017 at 18:24
9
$\begingroup$

This is known and it seems it is intentional. Even on the doc page of Histogram you can find examples of this behavior. It looks like the number specification is only seen as an order of magnitude indicator. A workaround would be to specify bin lists yourself.

Histogram[data, {-2, 3, 1}]

Mathematica graphics

$\endgroup$
6
  • 5
    $\begingroup$ But bspec clearly says "use n bins"... The documentation must be wrong then? I'm surprised I've never come across this given how much I use histograms... Probably because I always specify the bin widths for uniformity across datasets $\endgroup$
    – rm -rf
    Commented Jun 30, 2012 at 17:02
  • 1
    $\begingroup$ Mathematica used to have a histogram option called ApproximateIntervals which could be used to set the interval boundaries to be simple numbers or not. 'Simple numbers' seems to be the only behaviour now. You have to set them yourself now if you want specific intervals. Here's the old documentation page: reference.wolfram.com/mathematica/Histograms/ref/Histogram.html $\endgroup$ Commented Jun 30, 2012 at 18:21
  • $\begingroup$ @R.M I know I've seen this a couple of years ago. May have even asked a question about it myself on mathgroup, but couldn't find it right now. I agree the documentation is incorrect here. $\endgroup$ Commented Jun 30, 2012 at 19:29
  • $\begingroup$ @R.M 't was here $\endgroup$ Commented Jun 30, 2012 at 21:48
  • $\begingroup$ @SjoerdC.deVries Yes, ajasja remembered and answered with that already... $\endgroup$
    – rm -rf
    Commented Jun 30, 2012 at 21:50
6
$\begingroup$

Looking through the internal code for Histogram and following the rabbit hole, this behaviour is clearly intentional and the documentation is definitely misleading. The code for Histogram has a "main" function that looks something like the following:

mainFunction[args__, o : OptionsPattern[]] := 
 Block[{data, stuff, width, height},
    data = First@{args};
    stuff = Rest@{args};
    {width, height} = Switch[Length@stuff,
            0, {Automatic, Automatic},
            1, {First@stuff, Automatic},
            2, stuff
        ];
    ...
  ]

If you continue down other related functions, you'll observe that nowhere do they interpret the argument as number of bins, but only as widths, which are then smoothed with a default smoothing function.

Hence, even though the documentation says that using n for bspec uses n bins, the implementation does not reflect it.

$\endgroup$
1
  • $\begingroup$ Finding this 8 year old post looking for an explanation; the documentation still says the same thing, and the implementation does not reflect this. $\endgroup$ Commented Jul 13, 2020 at 16:57
3
$\begingroup$

As an alternative to Sjoerd C. de Vries answer, you could construct your own histogram with the numbers of bins you want to have with BinCounts Just as an easy example (I am sure it can be better written and a lot of things can be done better):

data = RandomVariate[NormalDistribution[0, 1], 200];      
startValue=-2.5;
endValue=3.5;
binWidth=1;
scale=Table[startValue+i*binWidth,{i,0,(endValue-startValue)/binWidth-1}](*shift the bin center as you like!*);
binnedData=BinCounts[data,{startValue,endValue,binWidth}];
forPlot=Transpose[{scale,binnedData}];

By using

ListPlot[forPlot,InterpolationOrder->0,Filling->Axis,Joined→True]

You will get:

HistogramWithBinCounts

$\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.