I am trying to create a dumbbell chart comparing baseline to endline values along several metrics and I am so close to having it just how I want it. I start with this data:
> dput(mydata)
structure(list(category = c("food security", "food security",
"child survival", "child survival", "boosted incomes", "boosted incomes",
"empowered churches", "empowered churches", "food security",
"food security", "child survival", "child survival", "boosted incomes",
"boosted incomes", "empowered churches", "empowered churches"
), metric = c("Never going to bed hungry", "Children at a healthy weight",
"Poor health is not a \"serious problem\"", "No children sent to work in the city",
"Low income is not a \"serious problem\"", "At least one stable income source",
"Spiritual support is not a \"serious problem\"", "Women who feel hope for the future",
"Never going to bed hungry", "Children at a healthy weight",
"Poor health is not a \"serious problem\"", "No children sent to work in the city",
"Low income is not a \"serious problem\"", "At least one stable income source",
"Spiritual support is not a \"serious problem\"", "Women who feel hope for the future"
), round = c("baseline", "baseline", "baseline", "baseline",
"baseline", "baseline", "baseline", "baseline", "endline", "endline",
"endline", "endline", "endline", "endline", "endline", "endline"
), percentage = c(0.53, 0.79, 0.8, 0.8, 0.75, 0.72, 0.75, 0.53,
0.98, 0.93, 0.95, 0.96, 0.93, 0.94, 0.97, 0.84)), class = c("tbl_df",
"tbl", "data.frame"), row.names = c(NA, -16L))
and I run the following code to basically prepare it for my ggplot function
mydata <- mydata %>%
mutate(bump_percentage = if_else(round == "baseline", percentage - .03,
percentage .03)) %>%
mutate(bump_percentage = bump_percentage*100,
percentage = percentage*100) %>%
arrange(category, round) %>%
mutate(category = factor(category, c("food security", "child survival", "boosted incomes", "empowered churches")))
midpoints <- mydata %>%
group_by(metric) %>% summarise(midpoint = mean(percentage))
mydata <- mydata %>%
inner_join(midpoints, by = "metric")
It is not necessary to understand all of that to answer my question, but I provide it just in case my bug is somewhere I don't expect. the "bump" stuff is only there so I can create the percentage labels you'll see on the graph below.
My current issue is that I want to add arrows to indicate the passage of time (left to right). The midpoint variable is created to indicate the position of the arrows in the graph below.
After running the code above on the initial data, I use this:
ggplot(mydata, aes(x=percentage, y=metric, color=category))
geom_line(color="gray", size=1.75)
geom_path(aes(x = midpoint),
arrow = arrow(angle = 30, length = unit(.15, "inches"), type = "closed"),
color = "gray", )
geom_point(size=2) scale_color_viridis(discrete = T)
geom_text(aes(label=glue("{percentage}%"), x=bump_percentage), color = "dimgray", size=3)
theme_fivethirtyeight()
facet_grid(category ~ ., scales = "free_y", switch = "y")
theme(legend.title=element_blank(), axis.text.x = element_text(color = "dimgray"),
panel.grid.major.x = element_line(color="gray", size=.2),
panel.grid.major.y = element_line(color="gray", size=.2, linetype = "dashed"),
strip.placement = "outside",
panel.spacing.y = unit(0, "mm"),
strip.text = element_blank(),
legend.justification = 1)
scale_x_continuous(labels=glue("{seq(50,100,10)}%"))
which produces this:
WHY ARE THE ARROWS POINTED THE WRONG WAY? My first thought was that the data was simply ordered incorrectly, which is why I added round
to the arrange()
function you see above. That didn't do it for me.
I think that in my actual geom_path
call, there is something I need to do to indicate the direction of the arrows. Right now, the aes is only providing this one point, which doesn't specify a direction. But I am not sure what I am missing here.
CodePudding user response:
Your geom_path
is essentially a single point, so the arrow doesn't know which way it is 'supposed' to point. Instead, make it a segment
with a defined start and end (say, the midpoint and the midpoint 1), so that the segment has a definite direction:
library(glue)
library(ggthemes)
library(ggplot2)
ggplot(mydata, aes(percentage, metric, color = category))
geom_line(color = "gray", size = 1.75)
geom_segment(aes(x = midpoint, xend = midpoint 1, yend = metric),
arrow = arrow(angle = 30, length = unit(.15, "inches"),
type = "closed"),
color = "gray")
geom_point(size = 2)
scale_color_viridis_d()
geom_text(aes(label = glue("{percentage}%"), x = bump_percentage),
color = "dimgray", size = 3)
theme_fivethirtyeight()
facet_grid(category ~ ., scales = "free_y", switch = "y")
theme(legend.title = element_blank(),
axis.text.x = element_text(color = "dimgray"),
panel.grid.major.x = element_line(color = "gray", size = 0.2),
panel.grid.major.y = element_line(color = "gray", size = 0.2,
linetype = "dashed"),
strip.placement = "outside",
panel.spacing.y = unit(0, "mm"),
strip.text = element_blank(),
legend.justification = 1)
scale_x_continuous(labels = glue("{seq(50,100,10)}%"))
CodePudding user response:
Change the angle to 210 - or something like that. Points the other way.