Reputation: 32978
We are using dotplots in a classroom setting to introduce the histogram, because the binning concept is confusing to many students. So we start with the dotplot which is similar but more intuitive:
x <- rnorm(100)
qplot(x, geom = "bar")
qplot(x, geom = "dotplot", method="histodot")
Because students do this on their own data, the code needs to work without manual fiddling. However the geom_dotplot
seems to use different scaling defaults than geom_bar
. The y axis does not adjust with the data, but seems to depend only on the size of the dots. For example:
x <- runif(1000)
qplot(x, geom = "bar")
qplot(x, geom = "dotplot", method="histodot")
How can I make geom_dotplot
with stat_histodot
scale the y axis exactly as it would do for the histogram, either by using smaller or overlapping dots?
Upvotes: 7
Views: 1936
Reputation: 32978
I came up with the following workaround that shrinks the binwidth until things fit on the page:
# This function calculates a default binwidth that will work better
# for the dotplot with large n than the ggplot2 default.
calculate_smart_binwidth <- function(x, aspect_ratio = 2/3){
x <- as.numeric(x)
nbins <- max(30, round(sqrt(length(x)) / aspect_ratio))
range <- range(x, na.rm = TRUE, finite = TRUE)
if(diff(range) == 0) return(NULL)
repeat {
message("trying nbins: ", nbins)
binwidth <- diff(range)/nbins;
highest_bin <- max(ggplot2:::bin(x, binwidth = binwidth)$count);
if(highest_bin < aspect_ratio * nbins) return(binwidth)
nbins <- ceiling(nbins * 1.03);
}
}
Examples:
x <- runif(1e4)
qplot(x, geom="dotplot", binwidth=calculate_smart_binwidth(x))
x <- rnorm(1e4)
qplot(x, geom="dotplot", binwidth=calculate_smart_binwidth(x))
Upvotes: 3