1

How can I display a1 (random), a2 (random 2), a3 (random 3) in the legend instead of displaying the boxplot symbole?

The plot is here

The code I'm working with is

library(ggplot2)
library(reshape2)

B <- 25
datainit <- data.frame(v1 = 1:B, a1 = randl, a2 = rand2, a3 =  rand3)
idinit <- rep(c('a1', 'a2', 'a3'), each = B)
dat.minit <- melt(datainit, id.vars=idinit, measure.vars=c('a1', 'a2', 'a3'))
position <- c('a1', 'a2', 'a3')

plegend <- ggplot(dat.minit, aes(x = idinit, y = value, fill =  idinit)) +
 geom_boxplot(fill='white',color="darkred", show.legend = TRUE, width = 0.4) +     
 stat_boxplot(geom = "errorbar", width = 0.5, color="darkred") +
 labs(x =   "methods", y = "values")  +
 scale_x_discrete(limits = position)  +
 scale_fill_discrete(name="some\nmethods", 
    labels=c('random', 'random 2', 'random 3'))

The data is like

  v1        a1        a2        a3
1   1 0.6715123 0.6851999 0.6858062
2   2 0.6123710 0.6330409 0.6317203
Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
  • Probably easier to use a `geom_text` than a legend for this. Or more conventionally, put any additional description of the categories into a figure caption rather than the figure itself. – dww Nov 14 '17 at 23:54
  • You already have the groups illustrated on the x-axis. You can always change the labels there and remove the legend, as it would be redundant. – Jake Kaupp Nov 14 '17 at 23:57
  • Yes, I cound but some of the names are too big to display on x-axis. – Fatima Batool Nov 15 '17 at 00:01
  • @dww, thanks for the suggetion. I think explaing a1, ... in caption would be easier. – Fatima Batool Nov 15 '17 at 01:21

1 Answers1

1

One option could be to use grid commands to dig into the structure of the legend, and replace the boxplot keys with a1, a2, a3.

library(ggplot)
library(grid)

plegend <- ggplot(dat.minit, aes(x = idinit, y = value, fill =  idinit)) +
  geom_boxplot(fill='white',color="darkred", show.legend = TRUE, width = 0.4)      + 
  stat_boxplot(geom = "errorbar", width = 0.5, color="darkred") +
  labs(x =   "methods", y = "values")  +
  scale_x_discrete(limits = position)  +
  scale_fill_discrete(name="some\nmethods", 
    labels=c('random', 'random 2', 'random 3'))

# Get the plot grob
g = ggplotGrob(plegend )

# Get the legend
leg = g$grobs[[which(g$layout$name == "guide-box")]]

# Get the positions of keys in the legend layout
pos = grep("key-[0-9]+-1-1", leg$grobs[[1]]$layout$name)

# Get the labels
label = c("a1", "a2", "a3")

# Replace the keys with the labels
for(i in seq_along(pos)) {
   leg$grobs[[1]]$grobs[[pos[i]]] = textGrob(label[i], gp = gpar(cex = .75))
   }

# Put the legend back into the plot
g$grobs[[which(g$layout$name == "guide-box")]] = leg

# Draw it
grid.newpage()
grid.draw(g)
Sandy Muspratt
  • 31,719
  • 12
  • 116
  • 122
  • Brilliant, Thanks! – Fatima Batool Nov 15 '17 at 18:53
  • If I have 10 boxplots, this code is just changing the labels for first 7, as set in pos. So basically how to set the key? @Sandy – Fatima Batool Nov 15 '17 at 20:44
  • @FatimaBatool. The RegEx in line selecting the position was the problem. The '.' selected one character. When there are more than seven keys, the RegEx needs to select one or two characters. Try it now. Should be fixed. – Sandy Muspratt Nov 16 '17 at 07:09
  • How can I generekize this? So what if I have 12, 15, 17 boxplots? @Sandy I'hv tried different ranges `key-[0-15]` but now I can just see first 11 boxplots. – Fatima Batool Nov 17 '17 at 12:47
  • @FatimaBatool The posted code works for me, but `[0-15]` will not work. In regular expressions, `[0-9]` means 'any digit'; `+` means 'one or more'. So `key-[0-9]+-1-1` will select 'key-4-1-1', 'key-10-1-1'; and so forth. The 'name' column is `leg$grobs[[1]]$layout` gives the names of the grobs in the legend. You want to select the grobs whose names begin with 'key' but not ending with 'bg'. – Sandy Muspratt Nov 19 '17 at 01:07