R语言绘制跨时间点CTaa功能簇迁移Alluvial/Sankey图的问题求助
解决Alluvial图NA层问题的方案
你的问题出在数据整理阶段:使用pivot_wider后,仅在单个时间点存在的CTaa会在另一时间点列生成NA值,这些NA被当作有效分组,最终在绘图时形成额外的NA层。以下是两种解决思路,推荐第一种更简洁的长格式数据绘图方法:
方法一:使用长格式数据直接绘图(推荐)
无需将时间点转成宽格式,直接基于原始长格式数据统计频数后绘图,天然避免NA值的产生:
# 加载依赖包 library(tidyverse) library(ggalluvial) # 统计各分组的频数(如果你的count字段是单样本计数,用n()替代sum(count)) cd4_surv_summary <- cd4.surv.meta %>% group_by(CTaa, timepoint, functional.cluster, lks) %>% summarise(freq = sum(count), .groups = "drop") # 绘制Alluvial图 ggplot(cd4_surv_summary, aes(y = freq, axis = timepoint, stratum = functional.cluster, fill = CTaa)) + # 用CTaa作为连接标识,展示细胞类型在不同时间点功能簇的迁移 geom_alluvium(aes(connect = CTaa)) + # 绘制各时间点的功能簇层 geom_stratum() + # 添加层的标签 geom_text(stat = "stratum", aes(label = after_stat(stratum))) + # 按lks分面 facet_wrap(~lks) + # 隐藏图例(按需调整) theme(legend.position = "none") + # 指定时间点的显示顺序 scale_x_discrete(limits = c("Diagnosis", "Timepoint1"))
方法二:修复宽格式数据的NA问题
如果坚持使用宽格式数据,需要在绘图时过滤掉NA对应的层和连接:
library(tidyverse) library(ggalluvial) # 保留至少一个时间点有有效功能簇的行 filtered_data <- cd4.surv.meta %>% filter(!is.na(Diagnosis) | !is.na(Timepoint1)) ggplot(filtered_data, aes(axis1 = Diagnosis, axis2 = Timepoint1, y=freq)) + # 过滤掉连接到NA的带状 geom_alluvium(aes(fill=CTaa), filter = function(d) !is.na(d$x) & !is.na(d$xend)) + # 分别绘制两个轴的层,过滤NA geom_stratum(data = filtered_data %>% filter(!is.na(Diagnosis)), aes(axis = Diagnosis)) + geom_stratum(data = filtered_data %>% filter(!is.na(Timepoint1)), aes(axis = Timepoint1)) + # 过滤NA的标签 geom_text(stat = "stratum", aes(label = after_stat(stratum)), filter = function(d) !is.na(d$stratum)) + facet_wrap(~lks) + theme(legend.position = "none")
说明
- 方法一利用长格式数据的特性,每个时间点的功能簇独立统计,不会生成NA,是更符合Alluvial图数据逻辑的做法。
- 方法二则通过过滤NA值,避免无效的层和连接被绘制,但代码相对繁琐。
内容的提问来源于stack exchange,提问作者Alfredo Marchetti
相关产品推荐
相关产品推荐

