如何用ggrepel或其他方法为ggalluvial冲积图层级设置对齐标签
R语言ggalluvial冲积图标签外移实现方案
我使用R语言的ggalluvial包生成了若干冲积图。
下方的代码示例输出的效果已经接近我的预期,示例如下:
library("ggalluvial") par(mar = c(1,1,1,1)*12, cex = 0.6, xpd=NA) # 生成示例数据 somelongnames <- c("homo sapiens", "homo sapiens", letters[18], "some other long name", letters[seq(4)]) df <- data.frame(x = factor(somelongnames), y = factor(c("this label is long", "Golgi", letters[13:18])), count = c(2, 10, 4, 5, 5, 1, 9, 3)) ll <- unique(c(as.character(df$x), as.character(df$y))) grid.col <- rainbow(length(ll)) grid.col <- setNames(grid.col, ll) # 为冲积图设置配色(ggalluvial层级的配色需要按顺序设置,操作相对复杂) names(df) <- c("Condition1", "Condition2", "value") levs1 <- levels(df$Condition1) levs2 <- levels(df$Condition2) res1 <- unique(df$Condition1) res2 <- unique(df$Condition2) cond1_cols <- grid.col[levs1[levs1 %in% res1]] cond2_cols <- grid.col[levs2[levs2 %in% res2]] columnCols <- c(cond1_cols, cond2_cols) stratCols <- c(rev(cond1_cols), rev(cond2_cols)) # 绘制冲积图 q <- ggplot(df, aes(y = value, axis1 = Condition1, axis2 = Condition2)) + geom_alluvium(aes(fill = Condition1), width = 0) + scale_fill_manual(values = columnCols) + geom_stratum(width = 1/8, fill = paste0(stratCols), color = "white") + scale_x_discrete(limits = c("Condition1", "Condition2"), expand = c(.09, .09)) + scale_y_continuous(breaks = NULL) + theme_minimal() + theme(axis.ticks.y = element_blank(), axis.text.y = element_blank(), panel.grid.major.y = element_blank(), panel.grid.major.x = element_blank()) + theme(legend.position = "none") + ylab(NULL) # 添加标签 q + geom_label(stat = "stratum", aes(label = after_stat(stratum)), color = stratCols, fontface = "bold", size = 3)

我希望将标签移动到层级的左右外侧,避免和图表重叠(标签较长时该问题尤其突出),我看到有案例使用ggrepel包实现该效果。
我参照相关方案,尝试在geom_text_repel的aes参数中使用for循环和ifelse语句,但没能写出正确的代码。请问有人可以提供帮助,或者有更优的解决方案吗?
使用ggrepel的失败代码示例如下:
q + ggrepel::geom_text_repel( aes(label = ifelse(Condition1 == as.character(res1)[1],as.character(res1)[1], NA)), stat = "stratum", size = 4, direction = "y", nudge_x = -.5 )

我理想的最终效果是标签全部置于冲积图左右两侧,不会和层级块重叠。
解决方案
你不需要使用循环或者逐条件判断,直接通过after_stat(x)识别当前标签所属的轴,再配合nudge_x的正负值控制左右偏移即可,完整实现代码如下:
library(ggrepel) # 基于你已生成的绘图对象q直接添加标签 q + geom_text_repel( aes( label = after_stat(stratum), # 按所属轴设置x方向偏移:左侧轴向左挪,右侧轴向右挪 nudge_x = after_stat(ifelse(x == 1, -0.3, 0.3)) ), stat = "stratum", size = 3, fontface = "bold", color = stratCols, # 仅y方向调整避免横向偏移 direction = "y", # 不需要引导线可将segment.color设为NA segment.color = "gray50", segment.size = 0.2, # 允许标签超出绘图区域 xlim = c(NA, NA), ylim = c(NA, NA) ) + # 扩大x轴范围容纳外侧标签 scale_x_discrete( limits = c("Condition1", "Condition2"), expand = c(0.3, 0.3) )
实现说明
- 核心逻辑是用
after_stat(x)读取stratum统计计算后得到的轴位置,1对应左侧Condition1轴,2对应右侧Condition2轴,自动适配偏移方向 - 调整
scale_x_discrete的expand参数,给左右两侧留出足够空间放置长标签 - 如果不需要标签和层级块之间的引导线,将
segment.color设为NA即可隐藏
内容的提问来源于stack exchange,提问作者lmsimp
相关产品推荐
相关产品推荐

