I'd like to a find a way to keep regular hexagons (all sides have equal length) when resizing hexbin plots in ggplot2 without manually adjusting the binwidth parameter.
To illustrate:
d <- ggplot(diamonds, aes(carat, price))+
stat_binhex(colour="white")
try(ggsave(plot=d,filename=<some file>,height=6,width=8))
yields hexagons that at least look regular to the eye:
And
try(ggsave(plot=d,filename=<some other file>,height=6,width=12))
yields irregular hexagons:
The documentation describes the binwidth parameter (e.g. binwidth = c(1, 1000)
) which specifies bin width. I'd like a function which, when given any plot size, returns the right binwidth settings to create regular hexagons.
Here's the solution to adjust binwidth dynamically. I've included handling for portrait aspect ratios and explicitly stated axis limits.
bins <- function(xMin,xMax,yMin,yMax,height,width,minBins) {
if(width > height) {
hbins = ((width/height)*minBins)
vbins = minBins
} else if (width < height) {
vbins = ((height/width)*minBins)
hbins = minBins
} else {
vbins = hbins = minBins
}
binwidths <- c(((xMax-xMin)/hbins),((yMax-yMin)/vbins))
return(binwidths)
}
For example this code:
h = 5
w = 5
yMin = min(diamonds$price)
yMax = max(diamonds$price)
xMin = min(diamonds$carat)
xMax = max(diamonds$carat)
minBins = 30
d <- ggplot(diamonds, aes(x = carat, y = price))+
stat_binhex(colour="white", binwidth = bins(xMin,xMax,yMin,yMax,h,w,minBins))+
ylim(yMin,yMax)+
xlim(xMin,xMax)
try(ggsave(plot=d,filename=<some file>,height=h,width=w))
Yields:
And when we change the width:
w = 8
d <- ggplot(diamonds, aes(x = carat, y = price))+
stat_binhex(colour="white", binwidth = bins(xMin,xMax,yMin,yMax,h,w,minBins))+
ylim(yMin,yMax)+
xlim(xMin,xMax)
try(ggsave(plot=d,filename=<some file>,height=h,width=w))
Or change the height:
h = 8
w = 5
d <- ggplot(diamonds, aes(x = carat, y = price))+
stat_binhex(colour="white", binwidth = bins(xMin,xMax,yMin,yMax,h,w,minBins))+
ylim(yMin,yMax)+
xlim(xMin,xMax)
try(ggsave(plot=d,filename=<some file>,height=h,width=w))
We can also change the x and y limits:
h = 5
w = 5
xMin = -2
d <- ggplot(diamonds, aes(x = carat, y = price))+
stat_binhex(colour="white", binwidth = bins(xMin,xMax,yMin,yMax,h,w,minBins))+
ylim(yMin,yMax)+
xlim(xMin,xMax)
try(ggsave(plot=d,filename=<some file>,height=h,width=w))