23

I have a 2d histogram created with stat_bin2d in the ggplot2 package. I'd like to control both the number of breaks in the color gradient, as well as where those breaks are located. I'm sure I'm just overlooking something small, but I can't figure out how to control the breaks in the binning.

Example:

x <- rnorm(100)^2
y <- rnorm(100)^2
df <- data.frame(x,y)
require(ggplot2)
p <- ggplot(df, aes(x, y)) 
p <- p + stat_bin2d(bins = 20)
p + scale_colour_gradient2(breaks=c(1,2,3,4,5,6))

This produces:

enter image description here

This plot only has 3 breaks at c(5,10,15) despite my futile attempt to put breaks at c(1,2,3,4,5,6))

Any hints?

JD Long
  • 59,675
  • 58
  • 202
  • 294

2 Answers2

20

here is an example combining cut and bin2d:

p <- ggplot(df, aes(x, y, fill=cut(..count.., c(0,6,8,9,Inf))))
p <- p + stat_bin2d(bins = 20)
p + scale_fill_hue("count")

As there are many ways to make the breaks arbitrary, if you define clearly what you want, probably you can get a better answer.

enter image description here

kohske
  • 65,572
  • 8
  • 165
  • 155
  • I can't get a better answer than this. It's exactly what I was looking for. Thanks! – JD Long Jul 26 '11 at 15:24
  • I like the solution, but I wonder if there is a way to get the scale to be marked at the (0, 6, 8, 9, Inf) breakpoints rather than denote them by ranges. – W7GVR Apr 20 '17 at 12:23
13

Me thinks you probably want the less talked about cousin of scale_colour_gradient2(), scale_fill_gradient2()

Using your data:

p + scale_fill_gradient2(breaks=c(1,2,3,4,5,6))

Also note the optional parameters low, mid, and high for additional controls.

enter image description here

Chase
  • 67,710
  • 18
  • 144
  • 161
  • 5
    The colours in the legend do not match those used on the plot. – Gavin Simpson Jul 22 '11 at 18:52
  • @Gavin - hmm, good catch. It looks like the entire range of values is being plotted, and breaks are only shown where specified...a bit strange. I wonder if that's the intended action? Regardless, adding `limits = c(1,6)` seems to give more intuitive values for the legend to match what is actually plotted. There may be other alternatives as well, so this isn't meant to be exhaustive. – Chase Jul 22 '11 at 18:59
  • @Gavin @Chase - Setting `limits = c(1,6)` makes the legend colors match the plots (for me at least) but I confess I don't have an explanation. – joran Jul 22 '11 at 22:16
  • 2
    Breaks are like axis tick marks. Changing them just changes the legend, it doesn't modify the scale in any way. – hadley Jul 23 '11 at 02:51
  • 2
    Also I doubt you really want gradient2 give that there's no natural midpoint. – hadley Jul 23 '11 at 02:52
  • Hadley, is there a way to change the scale? – JD Long Jul 23 '11 at 18:41
  • @JDLong What part of scale do you want to change? If you tell a desired output, maybe I can tell something. – kohske Jul 25 '11 at 03:12
  • @kohske, I just want to make the breaks arbitrary. This example is, of course, just a simple illustration of the problem. An example would be to make 4 buckets: 1-6, 6-8, 8, >9. – JD Long Jul 25 '11 at 16:38
  • @JD - you could always define your buckets previously with `cut` and then pass that as the aesthetic. – Chase Jul 25 '11 at 16:57
  • @chase, possibly because I don't use `ggplot` very much, but I don't know how to define the buckets with `cut` and pass that as an aesthetic. Sounds like the basis of a good answer thought! – JD Long Jul 25 '11 at 17:26
  • @JD - looks like kohske picked up on my random musings and offered a pretty slick solution. I think he's leading you on the path to ggplot righteousness. – Chase Jul 26 '11 at 12:49