基于ggalluvial的临床数据桑基图优化问题问询
ggalluvial临床数据冲积图问题解决方案
问题1:冲积流异常交叉的解决
原因
ggalluvial默认会对每个轴的所有类别(包括NA)按因子/字母顺序排序,未完成后续治疗的患者路径中的NA会被分散到不同位置,破坏路径连续性,导致冲积流交叉;同时默认的冲积流排序逻辑未优先保留最后一次有效治疗后的路径一致性。
解决方法
- 统一NA的因子位置:手动指定每个轴的因子水平,将NA放在最后,确保未完成治疗的患者的NA处于同一层级(其他轴同理):
# 示例:设置RP1x和RP1_risp的因子水平 SANKEY2$RP1x <- factor(SANKEY2$RP1x, levels = c("复发", "进展", NA)) SANKEY2$RP1_risp <- factor(SANKEY2$RP1_risp, levels = c("CR", "PR", "SD", "PD", NA))
- 强制路径连续排序:在
geom_alluvium中添加order = after_stat(stratum),让冲积流按当前轴的层顺序排列,避免交叉:
ggplot(data = SANKEY2, aes(axis1= RP0_risp, axis2= RP1x, axis3=RP1_risp, axis4=RP2x, axis5=RP2_risp, axis6=RP3x, axis7=RP3_risp, axis8=`Status at last contact`, y= Freq))+ geom_alluvium(aes(fill = RP0_risp, order = after_stat(stratum)), alpha=0.35)+ geom_stratum()+ geom_text(stat = "stratum", aes(label = after_stat(stratum)))+ theme_void()
- 清理数据路径:确保未完成3次治疗的患者,后续所有未发生事件的列均为NA(比如仅接受1次治疗的患者,RP2x、RP2_risp、RP3x、RP3_risp全为NA),避免出现部分NA、部分非NA的断裂路径。
问题2:Y轴反转/列值排序优化
解决方法
不要直接反转Y轴,通过调整因子水平或stat层的排序逻辑实现更稳定的效果:
- 自定义因子水平顺序:把需要在顶部显示的类别放在因子水平的最前面,直接控制层的上下位置:
# 示例:将初始治疗反应按从差到好排列,顶部显示PD SANKEY2$RP0_risp <- factor(SANKEY2$RP0_risp, levels = c("PD", "SD", "PR", "CR"))
- stat层反向排序配合冲积流同步:通过
stat_stratum(reverse = TRUE)反转层的顺序,同时让冲积流同步反向:
ggplot(data = SANKEY2, aes(axis1= RP0_risp, axis2= RP1x, axis3=RP1_risp, axis4=RP2x, axis5=RP2_risp, axis6=RP3x, axis7=RP3_risp, axis8=`Status at last contact`, y= Freq))+ geom_alluvium(aes(fill = RP0_risp, order = after_stat(-stratum)), alpha=0.35)+ geom_stratum(reverse = TRUE)+ geom_text(stat = "stratum", aes(label = after_stat(stratum)), reverse = TRUE)+ theme_void()
问题3:事件列对分组(X轴靠近)
可行性
完全可行,通过自定义每个轴的X坐标实现分组。
实现方法
放弃默认的axis1-axis8映射,手动指定每个变量的X位置,将同一事件的两列设为相邻的小数值,再自定义X轴刻度:
# 先添加唯一ID列(用于关联冲积流路径) library(dplyr) SANKEY2 <- SANKEY2 %>% mutate(ID = row_number()) ggplot(data = SANKEY2) + # 映射每个变量到自定义X位置 geom_alluvium(aes(x = 1, y = Freq, stratum = RP0_risp, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 2, y = Freq, stratum = RP1x, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 2.2, y = Freq, stratum = RP1_risp, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 3, y = Freq, stratum = RP2x, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 3.2, y = Freq, stratum = RP2_risp, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 4, y = Freq, stratum = RP3x, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 4.2, y = Freq, stratum = RP3_risp, alluvium = ID, fill = RP0_risp), alpha=0.35) + geom_alluvium(aes(x = 5, y = Freq, stratum = `Status at last contact`, alluvium = ID, fill = RP0_risp), alpha=0.35) + # 添加各轴的层 geom_stratum(aes(x = 1, y = Freq, stratum = RP0_risp)) + geom_stratum(aes(x = 2, y = Freq, stratum = RP1x)) + geom_stratum(aes(x = 2.2, y = Freq, stratum = RP1_risp)) + geom_stratum(aes(x = 3, y = Freq, stratum = RP2x)) + geom_stratum(aes(x = 3.2, y = Freq, stratum = RP2_risp)) + geom_stratum(aes(x = 4, y = Freq, stratum = RP3x)) + geom_stratum(aes(x = 4.2, y = Freq, stratum = RP3_risp)) + geom_stratum(aes(x = 5, y = Freq, stratum = `Status at last contact`)) + # 添加层文本标签 geom_text(stat = "stratum", aes(x = 1, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 2, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 2.2, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 3, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 3.2, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 4, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 4.2, y = Freq, label = after_stat(stratum))) + geom_text(stat = "stratum", aes(x = 5, y = Freq, label = after_stat(stratum))) + # 设置X轴刻度和分组标签 scale_x_continuous(breaks = c(1,2.1,3.1,4.1,5), labels = c("初始治疗反应", "事件1", "事件2", "事件3", "最终状态")) + theme_void()
内容的提问来源于stack exchange,提问作者user238243
相关产品推荐
相关产品推荐

