Я прочитал все галлювиальные сообщения, которые смог найти, о порядке расположения осей на аллювиальной диаграмме. Каждая из моих осей является факторной переменной, и я установил уровни в том порядке, в котором я хочу, чтобы они отображались на графике. Первая из двух моих осей правильно упорядочена по уровням ее факторной переменной, и порядок меняется должным образом, когда я меняю уровни. Однако вторая ось не отражает уровни базовой факторной переменной. По какой-то причине вторая ось отражает уровни первой оси для всех перекрывающихся классов наркотиков и не реагирует на любые изменения, которые я вношу в уровни.
Есть ли у кого-нибудь предложения по решению этой проблемы?
Для справки, вот мои данные:
top_transitions <- data.frame(
last_pre_tx_drug = c("DPP4 inhibitors", "DPP4 inhibitors",
"Insulin", "Insulin", "Insulin",
"None", "None", "None", "None", "None",
"Sulfonylureas", "Sulfonylureas",
"Sulfonylureas", "Sulfonylureas"),
post_transplant_drug = c("Insulin", "Insulin + DPP4 inhibitors",
"Insulin", "None", "Insulin + GLP-1 RAs",
"DPP4 inhibitors", "Insulin", "None",
"Biguanides", "Sulfonylureas",
"Insulin + Sulfonylureas", "Insulin",
"None", "Sulfonylureas"),
N = c(1809, 1005, 35053, 4506, 808, 2200, 12087, 36052,
1304, 3303, 1301, 5017, 1302, 1207)
)
top_transitions$last_pre_tx_drug <- factor(top_transitions$last_pre_tx_drug,
levels = c("DPP4 inhibitors", "Insulin", "None", "Sulfonylureas"))
top_transitions$post_transplant_drug <- factor(top_transitions$post_transplant_drug,
levels = c("DPP4 inhibitors", "Insulin + Sulfonylureas",
"Insulin", "Insulin + DPP4 inhibitors", "None",
"Insulin + GLP-1 RAs", "Biguanides", "Sulfonylureas"))
И вот код, который я использую для своего сюжета:
# Color palette based on the levels of post_transplant_drug
color_palette <- c(
"DPP4 inhibitors" = "#4393C3",
"Insulin + Sulfonylureas" = "#B2182B",
"Insulin" = "#2166AC",
"Insulin + DPP4 inhibitors" = "#A6A6A6",
"None" = "#92C5DE",
"Insulin + GLP-1 RAs" = "#1B7837",
"Biguanides" = "#F4A582",
"Sulfonylureas" = "#D6604D"
)
library(ggalluvial)
ggplot(top_transitions, aes(axis1 = last_pre_tx_drug,
axis2 = post_transplant_drug, y = N)) +
geom_alluvium(aes(fill = post_transplant_drug),
width = 1/25, knot.pos = 0.1, curve_type = "sigmoid") +
geom_stratum(width = 1/5, fill = "#F0F0F0", color = "#808080") +
geom_text(stat = "stratum", aes(label = after_stat(stratum)),
size = 3.5, color = "#333333",
family = "Helvetica Neue", fontface = "bold",
hjust = 0.5, vjust = 0.5) +
scale_x_discrete(limits = c("last_pre_tx_drug", "post_transplant_drug"),
labels = c("Last Regimen Used\nPre-Transplant",
"First Regimen Used\nPost-Transplant"),
expand = c(.02, .02)) +
scale_fill_manual(values = color_palette, name = "Post-Transplant\nDrug Class") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5,
margin = margin(b = 10),
family = "Helvetica Neue"),
plot.subtitle = element_text(size = 12, hjust = 0.5,
margin = margin(b = 20),
family = "Helvetica Neue"),
axis.title = element_blank(),
axis.text = element_text(size = 11, color = "#333333", family = "Helvetica Neue"),
axis.text.y = element_blank(),
legend.position = "bottom",
legend.title = element_text(size = 11, face = "bold", family = "Helvetica Neue"),
legend.text = element_text(size = 10, family = "Helvetica Neue"),
panel.grid = element_blank(),
panel.border = element_blank(),
plot.margin = margin(20, 20, 20, 20))
Независимо от того, что я пытаюсь сделать, самая правая ось всегда выглядит следующим образом:





Одним из вариантов достижения желаемого результата было бы избавиться от общих уровней для обоих factor, для чего я просто добавляю суффикс "_2" к post_transplant_drug. После этого мы можем избавиться от суффикса, используя, например. gsub():
library(ggalluvial)
#> Loading required package: ggplot2
top_transitions$post_transplant_drug <- factor(
paste0(top_transitions$post_transplant_drug, "_2"),
levels = paste0(
c(
"DPP4 inhibitors", "Insulin + Sulfonylureas",
"Insulin", "Insulin + DPP4 inhibitors", "None",
"Insulin + GLP-1 RAs", "Biguanides", "Sulfonylureas"
), "_2"
)
)
names(color_palette) <- paste0(names(color_palette), "_2")
ggplot(top_transitions, aes(
axis1 = last_pre_tx_drug,
axis2 = post_transplant_drug, y = N
)) +
geom_alluvium(aes(fill = post_transplant_drug),
width = 1 / 25, knot.pos = 0.1, curve_type = "sigmoid"
) +
geom_stratum(width = 1 / 5, fill = "#F0F0F0", color = "#808080") +
geom_text(
stat = "stratum", aes(label = after_stat(
gsub("_2", "", stratum)
)),
size = 3.5, color = "#333333",
family = "Helvetica Neue", fontface = "bold",
hjust = 0.5, vjust = 0.5
) +
scale_x_discrete(
limits = c("last_pre_tx_drug", "post_transplant_drug"),
labels = c(
"Last Regimen Used\nPre-Transplant",
"First Regimen Used\nPost-Transplant"
),
expand = c(.02, .02)
) +
scale_fill_manual(
labels = \(x) gsub("_2", "", x),
values = color_palette, name = "Post-Transplant\nDrug Class"
) +
theme_minimal() +
theme(
plot.title = element_text(
face = "bold", size = 16, hjust = 0.5,
margin = margin(b = 10),
family = "Helvetica Neue"
),
plot.subtitle = element_text(
size = 12, hjust = 0.5,
margin = margin(b = 20),
family = "Helvetica Neue"
),
axis.title = element_blank(),
axis.text = element_text(size = 11, color = "#333333", family = "Helvetica Neue"),
axis.text.y = element_blank(),
legend.position = "bottom",
legend.title = element_text(size = 11, face = "bold", family = "Helvetica Neue"),
legend.text = element_text(size = 10, family = "Helvetica Neue"),
panel.grid = element_blank(),
panel.border = element_blank(),
plot.margin = margin(20, 20, 20, 20)
)

@M-- Абсолютно с тобой согласен. Но иногда полезно знать, как добиться желаемого результата с помощью небольшого хака. Напоминает подход Эрроу и Дебре для распространения теории общего равновесия (в экономике) на случай неопределенности: просто сделайте товары разными товарами, рассматривая состояние как характеристику.
Согласованный. Вы заставили меня рассказать о «небольшом хаке». "экономика" пролетела мимо моей головы ;)
Мы можем изменить форму данных, поместить обе оси в один столбец и применить соответствующий порядок/уровень факторов.
library(ggalluvial)
library(dplyr)
melted_top_transitions <- top_transitions %>%
tibble::rowid_to_column("ID") %>%
tidyr::pivot_longer(-c(ID, N)) %>%
mutate(value = factor(value,
levels = unique(c(levels(top_transitions$post_transplant_drug),
levels(top_transitions$last_pre_tx_drug))))) %>%
mutate(fclr = last(value), .by = ID)
Затем вам также необходимо изменить свой aes и предоставить:
Parameters `x`, `stratum`, and `alluvium` are required for data in lodes form
Я также использовал geom_flow вместо geom_alluvium (с последним почему-то не сработало). И чтобы «ширина линии» соответствовала N, нам нужно предоставить y для aes (ранее weight).
ggplot(melted_top_transitions,
aes(x = name, y = N,
stratum = value, alluvium = ID,
label = value)) +
geom_flow(aes(fill = fclr),
width = 1/25, knot.pos = 0.1, curve_type = "sigmoid") +
geom_stratum(width = 1/5, fill = "#F0F0F0", color = "#808080") +
geom_text(stat = "stratum", aes(label = after_stat(stratum)),
size = 3, color = "#333333",
family = "Helvetica Neue", fontface = "bold",
hjust = 0.5, vjust = 0.5) +
scale_x_discrete(limits = c("last_pre_tx_drug", "post_transplant_drug"),
labels = c("Last Regimen Used\nPre-Transplant",
"First Regimen Used\nPost-Transplant"),
expand = c(.02, .02)) +
scale_fill_manual(values = color_palette, name = "Post-Transplant\nDrug Class") +
theme_minimal() +
theme(plot.title = element_text(face = "bold", size = 16, hjust = 0.5,
margin = margin(b = 10),
family = "Helvetica Neue"),
plot.subtitle = element_text(size = 12, hjust = 0.5,
margin = margin(b = 20),
family = "Helvetica Neue"),
axis.title = element_blank(),
axis.text = element_text(size = 11, color = "#333333", family = "Helvetica Neue"),
axis.text.y = element_blank(),
legend.position = "bottom",
legend.title = element_text(size = 11, face = "bold", family = "Helvetica Neue"),
legend.text = element_text(size = 10, family = "Helvetica Neue"),
panel.grid = element_blank(),
panel.border = element_blank(),
plot.margin = margin(20, 20, 20, 20)) +
scale_y_discrete()

Это потрясающе. Я не осознавал, что смогу вот так расплавить таблицу или использовать эту структуру таблицы для сюжета. Большое спасибо!
Присмотревшись к этому более внимательно, я понимаю, что толщина потоков, похоже, не соответствует N, как раньше. Не могли бы вы объяснить, как мне этого добиться?
@jos0909 Ха!!! Вы правы, но я уверен, что раньше это работало (или, по крайней мере, у меня есть график, который я ранее создал для одного из своих отчетов с geom_flow вместо geom_alluvium, который имеет правильные веса). Кажется, это ошибка или что-то, что недавно изменилось. Позвольте мне прочитать некоторые изменения и документацию.
@jos0909 они кое-что поменяли. Мне следовало использовать y вместо weight, чтобы толщина работала. И у geom_alluvium было странное поведение (работало, когда у меня не было theme), поэтому я перешел на geom_flow. См. изменения выше;
Верная идея +1, но этот пример мне особенно не нравится. На мой взгляд,
axis1,axis2,axis3, .... следует использовать там, где ваши уровни принципиально различаются, например, скажем, пол, сфера деятельности, опыт. Для этого я предпочитаю изменить форму данных. Ваше здоровье. :)