ggplot2 multiple stat_binhex() plots with different color gradients in one image

荒凉一梦 提交于 2019-12-18 12:26:27

问题


I'd like to use ggplot2's stat_binhex() to simultaneously plot two independent variables on the same chart, each with its own color gradient using scale_colour_gradientn().

If we disregard the fact that the x-axis units do not match, a reproducible example would be to plot the following in the same image while maintaining separate fill gradients.

d <- ggplot(diamonds, aes(x=carat,y=price))+
  stat_binhex(colour="white",na.rm=TRUE)+
  scale_fill_gradientn(colours=c("white","blue"),name = "Frequency",na.value=NA)
try(ggsave(plot=d,filename=<some file>,height=6,width=8))

d <- ggplot(diamonds, aes(x=depth,y=price))+
  stat_binhex(colour="white",na.rm=TRUE)+
  scale_fill_gradientn(colours=c("yellow","black"),name = "Frequency",na.value=NA)
try(ggsave(plot=d,filename=<some other file>,height=6,width=8))

I found some conversation of a related issue in ggplot2 google groups here.


回答1:


Here is another possible solution: I have taken @mnel's idea of mapping bin count to alpha transparency, and I have transformed the x-variables so they can be plotted on the same axes.

library(ggplot2)

# Transforms range of data to 0, 1. 
rangeTransform = function(x) (x - min(x)) / (max(x) - min(x))

dat = diamonds
dat$norm_carat = rangeTransform(dat$carat)
dat$norm_depth = rangeTransform(dat$depth)

p1 = ggplot(data=dat) +
     theme_bw() +
     stat_binhex(aes(x=norm_carat, y=price, alpha=..count..), fill="#002BFF") +
     stat_binhex(aes(x=norm_depth, y=price, alpha=..count..), fill="#FFD500") +
     guides(fill=FALSE, alpha=FALSE) +
     xlab("Range Transformed Units")

ggsave(plot=p1, filename="plot_1.png", height=5, width=5)

Thoughts:

  1. I tried (and failed) to display a sensible color/alpha legend. Seems tricky, but should be possible given all the legend-customization features of ggplot2.

  2. X-axis unit labeling needs some kind of solution. Plotting two sets of units on one axis is frowned upon by many, and ggplot2 has no such feature.

  3. Interpretation of cells with overlapping colors seems clear enough in this example, but could get very messy depending on the datasets used, and the chosen colors.

  4. If the two colors are additive complements, then wherever they overlap equally you will see a neutral gray. Where the overlap is unequal, the gray would shift to more yellow, or more blue. My colors are not quite complements, judging by the slightly pink hue of the gray overlap cells.




回答2:


I think what you want goes against the principles of ggplot2 and the grammar of graphics approach more generally. Until the issue is addressed (for which I would not hold my breath), you have a couple of choices

Use facet_wrap and alpha

This is will not produce a nice legend, but takes you someway to what you want.

You can set the alpha value to scale by the computed Frequency, accessed by ..Frequency..

I don't think you can merge the legends nicely though.

library(reshape2)
# in long format
dm <- melt(diamonds, measure.var = c('depth','carat'))

ggplot(dm, aes(y = price, fill = variable, x = value)) + 
   facet_wrap(~variable, ncol = 1, scales  = 'free_x') + 
   stat_binhex(aes(alpha = ..count..), colour = 'grey80') + 
    scale_alpha(name = 'Frequency', range = c(0,1)) + 
    theme_bw() + 
    scale_fill_manual('Variable', values = setNames(c('darkblue','yellow4'), c('depth','carat')))

Use gridExtra with grid.arrange or arrangeGrob

You can create separate plots and use gridExtra::grid.arrange to arrange on a single image.

d_carat <- ggplot(diamonds, aes(x=carat,y=price))+
  stat_binhex(colour="white",na.rm=TRUE)+
  scale_fill_gradientn(colours=c("white","blue"),name = "Frequency",na.value=NA)

d_depth <- ggplot(diamonds, aes(x=depth,y=price))+
  stat_binhex(colour="white",na.rm=TRUE)+
  scale_fill_gradientn(colours=c("yellow","black"),name = "Frequency",na.value=NA)

library(gridExtra)


grid.arrange(d_carat, d_depth, ncol =1)

If you want this to work with ggsave (thanks to @bdemarest comment below and @baptiste)

replace grid.arrange with arrangeGrob something like.

ggsave(plot=arrangeGrob(d_carat, d_depth, ncol=1), filename="plot_2.pdf", height=12, width=8)


来源:https://stackoverflow.com/questions/13167531/ggplot2-multiple-stat-binhex-plots-with-different-color-gradients-in-one-image

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!