8

How to add a traditional legend to dumbbell plot created using ggalt::geom_dumbbell in R?

This question has an answer with an in-chart legend. How to map the aesthetics to get a separate legend for the points on the side/bottom ?

library(ggalt)

df <- data.frame(trt=LETTERS[1:5], l=c(20, 40, 10, 30, 50), r=c(70, 50, 30, 60, 80))

ggplot(df, aes(y=trt, x=l, xend=r)) + 
  geom_dumbbell(size=3, color="#e3e2e1", 
                colour_x = "red", colour_xend = "blue",
                dot_guide=TRUE, dot_guide_size=0.25) +
  theme_bw()

enter image description here

markus
  • 25,843
  • 5
  • 39
  • 58
Crops
  • 5,024
  • 5
  • 38
  • 65
  • 3
    It's easier to help you if you provide a [reproducible example](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) with sample input data. – MrFlick Jun 20 '17 at 13:30
  • @MrFlick the example is up. – Crops Jun 20 '17 at 19:36
  • So from the example, what do you want to be in the legend? – MrFlick Jun 20 '17 at 19:38
  • @MrFlick l = red and r = blue. They are two different columns in the data. I have tried individually plotting geom_point with scale_manual, but the mapping gets replaced. – Crops Jun 20 '17 at 19:58

1 Answers1

6

One way to get a legend is to add a points layer based on the dataset in long format, mapping color to the grouping variable.

First, make a long format dataset via gather from tidyr.

df2 = tidyr::gather(df, group, value, -trt)

Then make the plot, adding the new points layer with the long dataset and using scale_color_manual to set colors. I moved the geom_dumbbell specific aesthetics into that layer.

ggplot(df, aes(y = trt)) + 
     geom_point(data = df2, aes(x = value, color = group), size = 3) +
     geom_dumbbell(aes(x = l, xend = r), size=3, color="#e3e2e1", 
                   colour_x = "red", colour_xend = "blue",
                   dot_guide=TRUE, dot_guide_size=0.25) +
     theme_bw() +
     scale_color_manual(name = "", values = c("red", "blue") )

enter image description here

aosmith
  • 34,856
  • 9
  • 84
  • 118
  • This is awesome - the only downside is that the ordering of my factors (y-axis) gets wiped out when I include the `geom_point` layer. Any idea how to add the legend and also maintain the custom-ordered factors? – ForceLeft415 Apr 01 '19 at 20:24
  • @ForceLeft415 Hmm, I'm not sure. Make sure your `trt` equivalent is in the same custom order in each dataset. I thought it might be that the "long" dataset didn't maintain the factor order, but it looks like the current version of `gather()` maintains the level order from the original dataset. – aosmith Apr 01 '19 at 20:49
  • and will this work on matplotlib? looks tricky plus @ForceLeft415 made a good point, there must be a better way – David Andrei Ned Dec 16 '19 at 17:51
  • 1
    @DavidAndreiNed This answer is specific to **ggplot2**. I have no idea how/if it would extend to matplotlib. Generally speaking, since the OP example doesn't have an issue with factor order, setting the factor order of the dataset and then plotting is a fairly common approach for controlling ggplot2 axis order. Other options include setting the `limits` and/or `breaks` in the appropriate `scale_*()` function. – aosmith Dec 16 '19 at 18:43