And going one step further, adding the averages:
library(tidyverse)
DF <- data.frame(Party = rep(c("Dem", "Rep"), each = 100),
Value = c(rnorm(100, 45, 10), rnorm(100, 63, 12)),
YMin = rep(c(0,1), each = 100),
YMax = rep(c(0.5,1.5), each = 100))
DF_avg <- DF %>%
mutate(avg = mean(Value)) %>%
group_by(Party, avg, YMin, YMax) %>%
summarize(avg_party = mean(Value))
#> `summarise()` regrouping output by 'Party', 'avg', 'YMin' (override with `.groups` argument)
ggplot(DF, aes(x = Value, color = Party, ymin = YMin, ymax = YMax)) +
geom_linerange(alpha = 0.5) +
geom_linerange(data = DF_avg,
aes(x = avg_party, color = Party, ymin = YMin - .1, ymax = YMax + .1),
size = 2) +
geom_vline(data = DF_avg,
aes(xintercept = DF_avg$avg), size = 1) +
geom_text(data = tibble(x = seq(0, 100, by = 20), y = .75, label = glue::glue("{seq(0, 100, by = 20)}%")),
aes(x = x, y = y, label = label),
inherit.aes = F,
color = "grey40",
size = 3.5) +
scale_colour_manual(values = c("red3", "royalblue3")) +
theme_minimal(base_size = 14) +
theme(legend.position = "none",
aspect.ratio = 0.2,
plot.title = element_text(hjust = 0.5),
# somehow theme_void isn't working, so switch off everything we don't need
panel.grid = element_blank(),
axis.text = element_blank(),
axis.title = element_blank()
) +
labs(title = "Republican landslide counties are \ngenerally whiter than Democratic ones")

Created on 2020-07-09 by the reprex package (v0.3.0)