Alex Reynolds
Alex Reynolds

Reputation: 96937

Add manual gradient legend in ggplot2

I am making a "bullseye" or "dart board" plot with ggplot2. I'd like to ask if there is a way to manually add a gradient legend to the figure I am making, or if there is a way to modify my procedure to add that legend.

Here is a reproducible dataset to work with:

step <- 0.1
frac <- seq(0, 1, step)
df <- data.frame(l=levels(cut(0, breaks=frac)),  o=frac[1:length(frac)-1], f=c(0.000, 0.028, 0.165, 0.151, 0.149, 0.129, 0.138, 0.060, 0.090, 0.088), cols=c('#0000FF','#4343FF','#FF4343','#FF6969','#FF7070','#FFA4A4','#FF8E8E','#9D9DFF','#F0F0FF','#E8E8FF'))

Here is what it looks like:

> df
df
           l   o     f    cols
1    (0,0.1] 0.0 0.000 #0000FF
2  (0.1,0.2] 0.1 0.028 #4343FF
3  (0.2,0.3] 0.2 0.165 #FF4343
4  (0.3,0.4] 0.3 0.151 #FF6969
5  (0.4,0.5] 0.4 0.149 #FF7070
6  (0.5,0.6] 0.5 0.129 #FFA4A4
7  (0.6,0.7] 0.6 0.138 #FF8E8E
8  (0.7,0.8] 0.7 0.060 #9D9DFF
9  (0.8,0.9] 0.8 0.090 #F0F0FF
10   (0.9,1] 0.9 0.088 #E8E8FF

Here is reproducible code to generate the plot:

library(ggplot2)
#pdf("test.pdf", width=8, height=8)
p <- ggplot() + ylim(0, 1) + geom_rect(aes(xmin=-1, ymin=df$o, xmax=1, ymax=df$o+step), fill=df$cols) + coord_polar() + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank())
print(p)
#dev.off()

And here is the plot that this code generates — basically, a set of concentric rings with a desired color fill:

Bullseye

I'd like to add a legend bar to this plot that displays a (linear) gradient from a start color to an end color, with labels using the min/max of df$f.

I can provide the start and end color manually from df — or from the first and last entries of a separate colorRampPalette object (not shown) — or provide the color array from the colorRampPalette object to provide the interpolated colors. I just don't know how to generate a legend object separate from the main plot.

Is there a way to manually construct and append such an object onto this plot?

A couple things I tried were to explore the guide_colourbar() object and the scale_colour_gradientn() object, but I was not able to get anything into my plot using these entities. Is there a way to use them here?

Upvotes: 2

Views: 3647

Answers (1)

Axeman
Axeman

Reputation: 35242

The easiest way to get a nice legend, you'll need to actually map things to your data, like the design intent behind ggplot.

Method 1, map fill to your color variable and use scale_identity to use the exact colors as provided:

ggplot(df) + 
  ylim(0, 1) + 
  geom_rect(aes(xmin = -1, ymin = o, xmax = 1, ymax = o + step, fill = cols)) + 
  coord_polar() + 
  scale_fill_identity(guide = guide_legend())

enter image description here

The legend leaves to be desired however, since it isn't continuous, it is ordered the wrong way around and it shows color codes instead of values for the labels. Additionally, the different colors aren't equidistant in their mapped values.

Method 2, you can use an actual continuous scale (which you haven't provided) in order to get an appropriate colorbar. Here is an attempt that you can work from, where I let ggplot create a continuous scale from your extreme values through white.

ggplot(df) + 
  ylim(0, 1) + 
  geom_rect(aes(xmin = -1, ymin = o, xmax = 1, ymax = o + step, fill = f)) + 
  coord_polar() + 
  scale_fill_gradient2(midpoint = mean(range(df$f)), low = '#0000FF', high = '#FF4343')

enter image description here

Upvotes: 4

Related Questions