3

Using ggplot2 in R, I can obtain a discrete color scale like the following: https://i.stack.imgur.com/7g4mf.png

This can be generated as seen here.

However, it does not look great. I'd like ro remove the spacing between the levels, and I thought that maybe I could switch to a continuous color scale, using scale_gradientn() and having a very steep gradient between different colors. This way I could use a continuous color scale, which has labels in the right places and looks great, instead of a discrete one.

However, this is the best I could come up with:

library(ggplot2)
ggplot(faithfuld, aes(waiting, eruptions)) +
  geom_raster(aes(fill = density)) +
  scale_fill_gradientn(
    colours = c("red", "green", "blue", "yellow"), 
    values=c(0, 0.25, 0.25001, 0.5, 0.5001, 0.75, 0.75001,1)
  )

enter image description here

Which clearly is not good enough, as significant color shifting can be seen between the 4 levels.

Is this possible at all in ggplot2?

AF7
  • 3,160
  • 28
  • 63
  • I have trouble understanding your goal. At first you say you want a continuous scale, but then you seem to imply that you actually want a discrete scale. – Roland May 24 '18 at 10:20
  • In the example, I want a discrete scale with 4 colors, but with the benefits of a continuous scale: values in-between colors, and no white spaces between color levels. I have tried to accomplish this in many ways in the past (see linked question), and thought that maybe using a continuous scale could work, if I could get the gradients to be infinitely steep. – AF7 May 24 '18 at 10:29

2 Answers2

2

Just use a discrete scale:

library(ggplot2)
faithfuld$classes <- cut(faithfuld$density, c(-Inf, 0.01, 0.02, 0.03, Inf))
ggplot(faithfuld, aes(waiting, eruptions)) +
  geom_raster(aes(fill = classes)) +
  scale_fill_manual(name = "density",
                    values = c("red", "green", "blue", "yellow"),
                    labels = c(0.01, 0.02, 0.03, "")) +
  guides(fill = guide_legend(label.vjust = -0.2))

enter image description here

Roland
  • 127,288
  • 10
  • 191
  • 288
  • This is the same approach I used in the linked question, and it has a number of disadvantages. First, you have to play around with label positioning values, and change them every time you change plot size, number of labels etc. Second, as soon as you play around with the legend (e.g. `theme(legend.position="bottom")`) you see that more tuning is required, which also requires more fiddling with custom values. – AF7 May 25 '18 at 10:10
  • If you want to do something unusual (and in my opinion you shouldn't do it at all), you should expect that fiddling is required. – Roland May 25 '18 at 10:15
  • It's not something unusual, it is something that all other plotting systems, including base graphics, can do. – AF7 May 25 '18 at 10:25
  • What you do goes against the grammar of graphics as I understand it. A continuous guide is connected to a continuous scale, a discrete guide is connected to a discrete scale. A continuous guide should never be used with a discrete scale. – Roland May 25 '18 at 10:32
  • Yes, I agree with this. This would be a workaround. Unfortunately the current discrete implementation in ggplot prevents the use of this common type of scales where labels are between boxes, to indicate intervals. – AF7 May 25 '18 at 10:57
0

you can use legend key height in theme set it as

 legend.key.height =  unit(0, 'lines')

and you are right some trial and error has to be done my plot looks as follows enter image description here