Невозможно изменить порядок осей в галлювиальном режиме

Я прочитал все галлювиальные сообщения, которые смог найти, о порядке расположения осей на аллювиальной диаграмме. Каждая из моих осей является факторной переменной, и я установил уровни в том порядке, в котором я хочу, чтобы они отображались на графике. Первая из двух моих осей правильно упорядочена по уровням ее факторной переменной, и порядок меняется должным образом, когда я меняю уровни. Однако вторая ось не отражает уровни базовой факторной переменной. По какой-то причине вторая ось отражает уровни первой оси для всех перекрывающихся классов наркотиков и не реагирует на любые изменения, которые я вношу в уровни.

Есть ли у кого-нибудь предложения по решению этой проблемы?

Для справки, вот мои данные:

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

Независимо от того, что я пытаюсь сделать, самая правая ось всегда выглядит следующим образом:

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
83
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Одним из вариантов достижения желаемого результата было бы избавиться от общих уровней для обоих 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)
  )

Верная идея +1, но этот пример мне особенно не нравится. На мой взгляд, axis1, axis2, axis3, .... следует использовать там, где ваши уровни принципиально различаются, например, скажем, пол, сфера деятельности, опыт. Для этого я предпочитаю изменить форму данных. Ваше здоровье. :)

M-- 06.06.2024 22:01

@M-- Абсолютно с тобой согласен. Но иногда полезно знать, как добиться желаемого результата с помощью небольшого хака. Напоминает подход Эрроу и Дебре для распространения теории общего равновесия (в экономике) на случай неопределенности: просто сделайте товары разными товарами, рассматривая состояние как характеристику.

stefan 06.06.2024 22:29

Согласованный. Вы заставили меня рассказать о «небольшом хаке». "экономика" пролетела мимо моей головы ;)

M-- 06.06.2024 22:36
Ответ принят как подходящий

Мы можем изменить форму данных, поместить обе оси в один столбец и применить соответствующий порядок/уровень факторов.

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

Это потрясающе. Я не осознавал, что смогу вот так расплавить таблицу или использовать эту структуру таблицы для сюжета. Большое спасибо!

jos0909 07.06.2024 00:21

Присмотревшись к этому более внимательно, я понимаю, что толщина потоков, похоже, не соответствует N, как раньше. Не могли бы вы объяснить, как мне этого добиться?

jos0909 07.06.2024 01:01

@jos0909 Ха!!! Вы правы, но я уверен, что раньше это работало (или, по крайней мере, у меня есть график, который я ранее создал для одного из своих отчетов с geom_flow вместо geom_alluvium, который имеет правильные веса). Кажется, это ошибка или что-то, что недавно изменилось. Позвольте мне прочитать некоторые изменения и документацию.

M-- 07.06.2024 01:35

@jos0909 они кое-что поменяли. Мне следовало использовать y вместо weight, чтобы толщина работала. И у geom_alluvium было странное поведение (работало, когда у меня не было theme), поэтому я перешел на geom_flow. См. изменения выше;

M-- 07.06.2024 02:00

Другие вопросы по теме