'Connect stack bar charts with multiple groups with lines or segments using ggplot 2
I am conducting a study of a number of patients with a disease, and using an ordinal scale assessment of functional status at 3 different time points. I want to connect multiple groups in stacked bar charts across these time points.
I looked at these topics and havent gotten it to work using these suggestions:
How to position lines at the edges of stacked bar charts
Draw lines between different elements in a stacked bar plot
Please see the graphical representation of how I ultimately want this figure to look from R (generated in PRISM) of the frequencies of each of these 6 ordinal values across the three time points (top group has no patients with ordinal score 3,5,6):
Data:
library(tidyverse)
mrs <-tibble(
Score = c(0,1,2,3,4,5,6),
pMRS = c(17, 2, 1, 0, 1, 0, 0),
dMRS = c(2, 3, 2, 6, 4, 2, 2),
fMRS = c(4, 4, 5, 4, 1, 1, 2)
And this is the code that ive tried so far before I run in to issues using either geom_line or geom_segment (left out thse lines because it just distorts the figure currently)
mrs <- mrs %>% mutate(across(-Score,~paste(round(prop.table(.) * 100, 2)))) %>%
pivot_longer(cols = c("pMRS", "dMRS", "fMRS"), names_to = "timepoint") %>%
mutate(Score=as.character(Score),
value=as.numeric(value)) %>%
mutate(timepoint = factor(timepoint,
levels= c("fMRS",
"dMRS",
"pMRS"))) %>%
mutate(Score = factor(Score,
levels = c("6","5","4","3","2","1","0")))
mrs %>% ggplot(aes(y= timepoint, x= value, fill= Score))+
geom_bar(color= "black", width = 0.6, stat= "identity") +
scale_fill_manual(name= NULL,
breaks = c("6","5","4","3","2","1","0"), values= c("#000000","#294e63", "#496a80","#7c98ac", "#b3c4d2","#d9e0e6","#ffffff"))+
scale_y_discrete(breaks=c("pMRS",
"dMRS",
"fMRS"),
labels=c("Pre-mRS, (N=21)",
"Discharge mRS, (N=21)",
"Followup mRS, (N=21)"))+
theme_classic()
Solution 1:[1]
You're essentially creating an alluvial diagram. You could make use of the ggalluvial package. Below the desired look - I kept it in horizontal fashion, because it's more natural to read time points from left to right (at least in Western societies). But you can simply add coord_flip if you really want to.
Also - please see below a suggestion of what I personally find a more compelling visualisation.
Check the following sources for more info on alluvial charts
- https://corybrunson.github.io/2019/09/13/flow-taxonomy/
- https://matthewdharris.com/2017/11/11/a-brief-diversion-into-static-alluvial-sankey-diagrams-in-r/
library(tidyverse)
library(ggalluvial)
# I personally prefer to create a new object when you do data modifications
mrs_long <-
mrs %>% mutate(across(-Score,~paste(round(prop.table(.) * 100, 2)))) %>%
pivot_longer(cols = c("pMRS", "dMRS", "fMRS"), names_to = "timepoint") %>%
mutate(Score=as.character(Score),
value=as.numeric(value),
## I've reversed the level order
timepoint = factor(timepoint, levels= rev(c("fMRS", "dMRS", "pMRS"))),
Score = factor(Score, levels = 6:0))
ggplot(mrs_long,
aes(y = value, x = timepoint)) +
geom_flow(aes(alluvium = Score), alpha= .9,
lty = 2, fill = "white", color = "black",
curve_type = "linear",
width = .5) +
geom_col(aes(fill = Score), width = .5, color = "black") +
scale_fill_manual(NULL, breaks = 6:0,
values= c("#000000","#294e63", "#496a80","#7c98ac", "#b3c4d2","#d9e0e6","#ffffff"))+
scale_y_continuous(expand = c(0,0)) +
cowplot::theme_minimal_hgrid()
#> Warning: The `.dots` argument of `group_by()` is deprecated as of dplyr 1.0.0.
#> This warning is displayed once every 8 hours.
#> Call `lifecycle::last_lifecycle_warnings()` to see where this warning was generated.

Arguably more compelling - I find the message gets across better by making the full use of the "alluvial look". For example this could look like this:
ggplot(mrs_long,
aes(y = value, x = timepoint, fill = Score)) +
geom_alluvium(aes(alluvium = Score), alpha= .9, color = "black") +
scale_fill_manual(NULL, breaks = 6:0,
values= c("#000000","#294e63", "#496a80","#7c98ac", "#b3c4d2","#d9e0e6","#ffffff"))+
scale_y_continuous(expand = c(0,0)) +
cowplot::theme_minimal_hgrid()

Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
