Problems specifying number of bins in Histogram

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:

Histogram[data, 6]still gives seven bins:

Histogram[data, 7] also gives seven bins:

But Histogram[data, 10] gives thirteen bins:

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?

-
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 – R. M. Jun 30 '12 at 17:01
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"... – Jens Jun 30 '12 at 17:01
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. – Heike Jun 30 '12 at 18:08

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}]


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

-
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 – R. M. Jun 30 '12 at 21:28
+1, good to know. Doesn't work on v.7 I confirm. – Chris Degnen Jun 30 '12 at 21:45
Works on 9.0.1.0. Thanks ! – A.G. Jan 27 '15 at 22:02

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}]


-
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 – R. M. Jun 30 '12 at 17:02
+1 and congratulations for reaching 9966. – Jens Jun 30 '12 at 17:45
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 – Chris Degnen Jun 30 '12 at 18:21
@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. – Sjoerd C. de Vries Jun 30 '12 at 19:29
@R.M 't was here – Sjoerd C. de Vries Jun 30 '12 at 21:48

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.

-

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:

-