Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent ggplot2 from combining key glyphs? [duplicate]

Tags:

r

ggplot2

ggplot2 combines glyphs for the same scale which leads to confusing behaviour when using geom_hline and geom_vline to show two perpendicular lines as the key glyph for each color contains a cross (+) rather than | or - in correspondence to that color. How to prevent ggplot from combining - and | key glyphs?

library(ggplot2)
means = as.data.frame(t(colMeans(mtcars)))

(
    ggplot(mtcars, aes(x = disp, y = drat))
    + geom_point()
    + geom_hline(data = means, aes(color = 'average disp', yintercept = drat))
    + geom_vline(data = means, aes(color = 'average drat', xintercept = disp))
)

enter image description here

I tried setting key_glyph explicitly for both the geom_vline and geom_hline but it does not change anything.

Note: aside of the ease of interpretation, this is crucial for creating colorblind-friendly plots.

like image 859
krassowski Avatar asked Feb 02 '21 00:02

krassowski


2 Answers

Possible hacks off the top of my mind:

  1. Disguise a shape legend (with horizontal & vertical lines) as a colour legend (pro: less manual work than the following approaches; con: difficult to map the shape aesthetic to anything else)

  2. Convert the ggplot2 object to a grob object via ggplotGrob, & remove the offending grobs for horizontal / vertical line segments there (pro: doesn't affect any other aesthetic or require other packages; con: require familiarity with grob modifications & manual work for each plot)

  3. Create separate plots with only the desired legend items, then combine the legends together using one of the many available packages such as patchwork or cowplot (pro: can deal with any combination of desired legend; con: require familiarity with other packages + manual labour to tweak the plots' appearances)

I haven't looked into modifying the underlying ggplot code itself just yet, because I feel that under most circumstances, combining glyphs is a desirable end. Legend for horizontal and vertical lines is a valid exception, but not a particularly common one. So I'd go with hacks for now.

Demonstration for the first hack below:

ggplot(mtcars, aes(x = disp, y = drat)) + 
  geom_point() + 
  geom_hline(data = means, aes(color = 'average disp', yintercept = drat),
             show.legend = F) +
  geom_vline(data = means, aes(color = 'average drat', xintercept = disp),
             show.legend = F) +
  geom_point(data = data.frame(val = c(means$drat, means$disp), 
                               name = c("average disp", "average drat")),
             aes(x = 150, y = 3, # arbitrary values, anything within the plot's range
                 color = name, shape = name),
             alpha = 0,          # don't actually show the point in the plot
             size = 5,           # adjust size / stroke to suit your plot's size
             stroke = 2) +
  scale_shape_manual(name = "colour",
                     values = c("average disp" = "\U2014", # horizontal line
                                "average drat" = "\U007C"),# vertical line
                     guide = guide_legend(override.aes = list(alpha = 1)))

result

like image 196
Z.Lin Avatar answered Nov 16 '22 20:11

Z.Lin


As per this answer to the same question (this was asked recently) - create a second scale. In the linked question you will also find a related GitHub issue, here for your convenience.

library(ggplot2)
library(ggnewscale)
means = as.data.frame(t(colMeans(mtcars)))

  ggplot(mtcars, aes(x = disp, y = drat))+
    geom_point()+
    geom_hline(data = means, aes(color = 'average disp', yintercept = drat))+
    scale_color_manual(values = "red", name = NULL) +
    new_scale_color() +
    geom_vline(data = means, aes(color = 'average drat', xintercept = disp)) +
    scale_color_manual(values = "blue", name = NULL)

Created on 2021-02-02 by the reprex package (v0.3.0)

like image 4
tjebo Avatar answered Nov 16 '22 20:11

tjebo