3

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.

Mojoesque
  • 1,166
  • 8
  • 15
  • Maybe `geom_point(aes(group = name))`? Otherwise the points are grouped and dodged by color. – stefan Jul 07 '21 at 12:16
  • This puts each pair of points with the same name in one "dodge group". So there will be four groups of two points per grouping2 instead of the two groupings where all greenish and all reddish points are on top of each other (as seen above). The position of the points is where they are supposed to be in the plot I posted, but the lines are note. – Mojoesque Jul 07 '21 at 12:27
  • Okay. Now I understand what you are trying to achieve, i.e. connecting a red point with the respective green one. If that is right then one option would be to use adjust the x axis values manually instead of using `position_dodge`. – stefan Jul 07 '21 at 14:35
  • Yeah that's an option. How would you do that? Because the way I found ended up being quite hacky since the x-axis is categorical and of course the actual data is more complex than the toy example. – Mojoesque Jul 07 '21 at 14:45

2 Answers2

2

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)

stefan
  • 90,330
  • 6
  • 25
  • 51
  • Yeah that is one way that works and is similar to what I came up with so far. I would still like to find a less manual way of doing things, so I will leave the question open a bit longer. Thanks! – Mojoesque Jul 07 '21 at 15:00
0

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)

jan-glx
  • 7,611
  • 2
  • 43
  • 63