如何在ggsankey中跳过具有NA值的节点?

4

假设我有这个数据集(实际数据集有30多列和数千个ID)

    df <- data.frame(id = 1:5,
              admission = c("Severe", "Mild", "Mild", "Moderate", "Severe"),
              d1 = c(NA, "Moderate", "Mild", "Moderate", "Severe"),
              d2 = c(NA, "Moderate", NA, "Mild", "Moderate"),
              d3 = c(NA, "Severe", NA, "Mild", NA),
              d4 = c(NA, NA, NA, "Mild", NA),
              outcome = c("Dead", "Dead", "Alive", "Alive", "Dead"))

我想制作一个桑基图,以展示病人每日的严重程度变化情况。当观察值达到NA(表示已经达到某个结果)时,我希望节点直接链接到该结果。
以下是图表预期效果: enter image description here 图片来自@qdread提出的问题,这里 使用能够实现吗?
这是我的当前代码:
df.sankey <- df %>%
    make_long(admission, d1, d2, d3, d4, outcome)
ggplot(df.sankey, aes(x = x,
                     next_x = next_x,
                     node = node,
                     next_node = next_node,
                     fill = factor(node),
                     label = node)) +
    geom_sankey(flow. Alpha = 0.5,
                node. Color = NA,
                show. Legend = TRUE) +
    geom_sankey_text(size = 3, color = "black", fill = NA, hjust = 0, position = position_nudge(x = 0.1))

编辑 根据@Allan Cameron提供的解决方案,我成功地绕过了带有NA值的节点。然而,由于指向targets的链接没有排序,所以图表看起来相当复杂。

    do.call(rbind, apply(df, 1, function(x) {
    x <- na.omit(x[-1])
    data.frame(x = names(x), node = x, 
               next_x = dplyr::lead(names(x)), 
               next_node = dplyr::lead(x), row.names = NULL)
})) %>%
    ggplot(df.sankey, aes(x = x,
                          next_x = next_x,
                          node = node,
                          next_node = next_node,
                          fill = factor(node),
                          label = node)) +
    geom_sankey(flow.alpha = 0.5,
                node.color = NA,
                show.legend = TRUE) +
    geom_sankey_text(size = 3, color = "black", fill = NA, hjust = 0, position = position_nudge(x = 0.1))

这导致了这个图表: enter image description here 是否可能对Outcome的target链接进行排序,以便所有具有Severe值的链接得到聚合?
感谢您提前的帮助。
2个回答

3

您只需要手动重塑数据,因为 make_long 在这里无法满足您的需求。

  do.call(rbind, apply(df, 1, function(x) {
    x <- na.omit(x[-1])
    data.frame(x = names(x), node = x, 
               next_x = dplyr::lead(names(x)), 
               next_node = dplyr::lead(x), row.names = NULL)
    })) %>%
    mutate(x = factor(x, names(df)[-1]),
           next_x = factor(next_x, names(df)[-1])) %>%
    ggplot(aes(x = x,
               next_x = next_x,
               node = node,
               next_node = next_node,
               fill = node,,
               label = node)) +
    geom_sankey(flow.alpha = 0.5,
                node.color = NA,
                show.legend = TRUE) +
    geom_sankey_text(size = 3, color = "black", fill = NA, hjust = 0, 
                     position = position_nudge(x = 0.1))

enter image description here


谢谢!这正是我一直在寻找的!您是否有任何关于如何对“Outcome”垂直栏中的直接链接进行排序的见解?由于真实数据集有数十列,因此分支看起来过于复杂,因为它们没有排序。 - amedicalenthusiast
更新:抱歉有额外的请求,我已经更新了数据集和代码行以说明问题。是否可以对节点进行排序? - amedicalenthusiast
@amedicalenthusiast 我认为在ggsankey接口内是不可能实现这个功能的,因为大多数位置选择都是在“StatSankeyFlow”中硬编码的,它实际上计算了多边形。你提出的建议听起来需要手动编码,因为选择将根据流的全局理解及其应该如何排列进行。我可以看到一种手动执行此操作的方法,但这将非常复杂,可能纯粹使用多边形在ggplot中完成。 - Allan Cameron
你可能想要使用riverplot包。 - Takuro Ikeda

1

将输出结果向左移动,然后绘制:

library(ggplot2)
library(dplyr)
library(ggsankey)

# fill NAs from last value
df[] <- t(apply(df, 1, zoo::na.locf, fromLast = TRUE))

head(df)
#   id admission       d1       d2     d3   d4 outcome
# 1  1    Severe     Dead     Dead   Dead Dead    Dead
# 2  2      Mild Moderate Moderate Severe Dead    Dead
# 3  3      Mild     Mild     Mild   Mild Mild   Alive
# 4  4  Moderate Moderate     Mild   Mild Mild   Alive
# 5  5    Severe   Severe Moderate Severe Dead    Dead

# then your existing code
df.sankey <- df %>%
  make_long(admission, d1, d2, d3, d4, outcome)

# ggplot...

enter image description here


谢谢您的快速回复!不填充NA并创建最后一个非空列与结果之间的直接连接是否可能?因为在真实数据集中,NA也可能意味着患者已经出院。提前致谢! - amedicalenthusiast
@amedicalenthusiast 然后用“discharged”填充NAs。但是,肯定有办法。 - zx8754
@amedicalenthusiast 再思考一下,然后“discharged”应该在结果列中。 - zx8754
感谢反馈。是的,我认为将那些在审查时仍然存活和那些已经出院的住院患者区分开来也是值得的。在当前形式中,两者都被编码为“存活”。 - amedicalenthusiast

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接