How to perform a non-equi-spaced histogram in R?

From the R docs for hist:

R's default with equi-spaced breaks (also the default) is to plot the counts in the cells defined by breaks. Thus the height of a rectangle is proportional to the number of points falling into the cell, as is the area provided the breaks are equally-spaced.

The default with non-equi-spaced breaks is to give a plot of area one, in which the area of the rectangles is the fraction of the data points falling in the cells.

So .. how do I get hist to plot non-equi-spaced breaks? It sounds as if it will calculate the breaks to end up with area one, but I don't see the options.

Edit: Also, what are recommended ways (in R) to do non-equi-spaced histograms? A typical case would be data that is spiky, causing all the action in one or a few cells, no matter how many are given as "breaks". Another would be two areas of activity separated by a large area of zero, meaning no matter how many breaks, all you see is flat, with two huge narrow spikes. Or perhaps worse, one area of activity, then another area of much less activity far away that causes the graph to be very wide and flat.

• This is a good question, but it appears to concern only how to get R to do something, as opposed to the statistical aspects of histograms. As such, I think it fits better on Stack Overflow than here. – gung May 24 '12 at 16:43
• I wouldn't mind knowing best practices for non-equi-spaced bins either but it seems odd to change the question now. – dfrankow May 24 '12 at 17:03
• Not at all, change away. You should insure that the question reflects what you want to know, so that you can get the info you need. Questions are often updated after initial posting to clarify what the OP is really after & to facilitate more appropriate answers. Also, it would make CV the appropriate place for the question IMO, should you want to keep it here. – gung May 24 '12 at 17:16

You will notice that there is an argument breaks as a part of the function hist(), with the default set to "Sturges". You can also set your own breakpoints and use them instead of the default sturges algorithm as follows:

breakpoints <- c(0, 1, 10, 11, 12)
hist(data, breaks=breakpoints)

If you read all the way down to the bottom, there are a couple of examples with non-equidistant breaks as well.

Update: This may not be a direct answer to your question, but you could use a different approach (i.e., graph) than a histogram. Personally, I don't find histograms terribly useful. Instead you could try a kernel density plot, which I think would address the first two cases you list (I don't see how you can get out of the third). In R, the code would be: plot(density(data)).

• Looks like no default way to get reasonable non-equi breakpoints (e.g., equal-area). Thanks. – dfrankow May 24 '12 at 17:02
• .. without computing them by some other function. – dfrankow May 24 '12 at 17:08

Denby and Mallows 2009 ungated linkprovide a nice approach called the 'diagonally cut histogram', and provide a function 'dhist' in their supplementary material (available at the above link).

Here is the abstract:

When constructing a histogram, it is common to make all bars the same width. One could also choose to make them all have the same area. These two options have complementary strengths and weaknesses; the equal-width histogram oversmooths in regions of high density, and is poor at identifying sharp peaks; the equal-area histogram oversmooths in regions of low density, and so does not identify outliers. We describe a compromise approach which avoids both of these defects. We regard the histogram as an exploratory device, rather than as an estimate of a density. We argue that relying on the asymptotics of integrated mean squared error leads to inappropriate recommendations for choosing bin-widths

And a figure comparing the a) cdf, b) equal area histogram, c) equal bin-width histogram and d) dhist: Lorraine Denby, Colin Mallows. Journal of Computational and Graphical Statistics. March 1, 2009, 18(1): 21-31. doi:10.1198/jcgs.2009.0002.

One easy solution would be to use quantiles as breaks:

x <- rnorm(100)
hist(x)
hist(x, breaks = quantile(x, 0:10 / 10))