Dodged dumbbell plots with ggplot2

I find nested groupings can often lead to difficulties with specific plots. In these situations I found the interaction() function to be very helpful since it allows for concise code and avoiding the data reformatting. We can define a new grouping for the line segments.

Importantly, the following solution works with position dodging because it uses geom_line() instead of geom_segment(). This avoids the xend aesthetic which position_dodge() can't handle.

ggplot(df) +
  geom_point(
    aes(
      x = Domain, y = pct_agreement, color = Area,
      shape = race, group = Area
    ), 
    position = position_dodge(width = 0.5)
  ) +
  geom_line(
    aes(
      x = Domain, y = pct_agreement, color = Area, 
      group = interaction(Area, Domain)
    ),
    position = position_dodge(width = 0.5)
  ) +
  coord_flip()

enter image description here


I'd define my own x values instead of dodge:

df <- data.frame(Domain, Area, race, pct_agreement) %>%
  mutate(myX = as.numeric(Domain) + ifelse(Area == "State", 0.25, -0.25))

df2 <- pivot_wider(df, names_from = race, values_from = pct_agreement)

ggplot(df) +
  geom_point(
    aes(
      x = myX, y = pct_agreement, color = Area, shape = race, group = Area
    )) +
  geom_segment(
    data = df2,
    aes(
      x = myX, xend = myX, y = White, yend = Black, color = Area
    )) +
  # fix the labels
  scale_x_continuous(name = "Domain", breaks = 1:7, labels = LETTERS[1:7]) +
  coord_flip()

It's also possible to mix the two approaches and dodge the points but use the calculated x values for the segments:

ggplot(df) +
  geom_point(
    aes(
      x = Domain, y = pct_agreement, color = Area, shape = race,
      group = Area
    ), 
    position = position_dodge(width = 1)
  ) +
  geom_segment(
    data = df2,
    aes(
      x = myX, xend = myX, y = White, yend = Black, color = Area
    )) +
  coord_flip()

Created on 2019-11-08 by the reprex package (v0.3.0)

Tags:

R

Ggplot2