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()
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)