How to combine position_dodge() and geom_line() with overlapping groupings?

Viewed 291

Is it possible to draw a line using geom_line() between dodged points, when the grouping variables on the x axis, the color and for the line overlap but are always different?

The grey lines in the plot below are supposed to always connect two datapoints with the same name, which are within the same grouping2 (x-axis) but in a different grouping2 (color).

Reproducible example:

library(tidyverse)

tbl = tibble(name = rep(paste("name", 1:12), each = 2), 
             grouping1 = rep(c("A", "B"), 12),
             grouping2 = c(rep("X", 8), rep("Y",8), rep("Z",8)),
             value = 1:24)

enter image description here

tbl %>%
  ggplot(aes(x = grouping2, y = value, color = grouping1)) +
    geom_line(aes(group = name),position= position_dodge(0.5), color = "grey44") +
    geom_point(position = position_dodge(0.5)) 

enter image description here

For my specific example there are some more or less hacky ways around this problem like using geom_segment() for the lines and turning the x-axis grouping2 into numeric or combining two groupings on the x-axis like grouping1 and grouping2.

Therefore, my question is if there is a clean way to achieve the desired plot?

There are some related questions like using position_dodge with geom_line , but they are not quite the same.

2 Answers

One option to achieve your desired result would be to convert your x axis variable to a numeric and adjust the positions manually instead of making use of position_dodge:

library(tidyverse)

tbl = tibble(name = rep(paste("name", 1:12), each = 2), 
             grouping1 = rep(c("A", "B"), 12),
             grouping2 = c(rep("X", 8), rep("Y",8), rep("Z",8)),
             value = 1:24)

width <- .125

tbl1 <- tbl %>%
  mutate(grouping2 = factor(grouping2),
         x = as.numeric(grouping2) + width * if_else(grouping1 == "A", -1, 1))

breaks <- unique(as.numeric(tbl1$grouping2))
labels <- unique(tbl1$grouping2)

ggplot(tbl1, aes(x = x, y = value, color = grouping1)) +
  geom_line(aes(group = name), color = "grey44") +
  geom_point() +
  scale_x_continuous(breaks = breaks, labels = labels)

Another workaround: use facets instead of dodging:

tbl %>%
  ggplot(aes(x = grouping1, y = value, color = grouping1)) +
  geom_line(aes(group = name), color = "grey44") +
  geom_point() +
  facet_wrap(vars(grouping2))

Created on 2021-11-26 by the reprex package (v2.0.1)

Related