堆叠柱状图各成分连线画法:突出展示组间物种丰度变化

本文介绍了如何使用R语言绘制堆叠柱状图,并通过添加组间连线来直观比较不同组间的差异。通过示例代码展示了从生成测试数据到利用tidyverse和ggplot2包进行数据转换和绘图的完整过程,特别适用于展示时间序列或梯度变化的数据。此外,还提供了一种适用于三组或更多组的通用画法,使得代码更具可复用性。
摘要由CSDN通过智能技术生成

堆叠柱状图连线画法

提出问题

宏基因组之前转载了中科院生态中心邓晔组的文章《土壤细菌定量方法结合相对丰度分析揭示种群的真实变化》。其中的图3基于堆叠柱状图,添加组间各成分连线,可以更容易的观察和比较组间的变化。如下图:

我在很多文章中也见过,一直没有学会具体的做法。这回正好身边的人会做,就问了一个作者,结果回复是origin画的,有个选项就可以添加组间连线。

现在方法是有了,不过我还是喜欢用R来画图,因为每一个细节的修改都落实的代码上,可见可重复。

而窗口操作类的软件,操作过程是不容易被记录的,别人也很难重复。

我下午将此问题放在了宏基因组0讨论群中,问是否有R包或现成的函数一句话实现在堆叠图中添加组间连线。

获取专业解答

李陈浩老师首先説写两句R就搞定。可是以我的R水平,虽然学过R in action,还只是会按帮助使用包,修改代码的水平,很难写代码实现想法。

同时李海敏、沈伟等几位老师,也提供了众多解决方案,如ggalluvial,这个更炫酷,功能过于强大,我会在下一次分享中把中文笔记和使用心得带给大家。

到了晚上,新加坡的李陈浩老师己经将我想要的功能帮助写好了,大赞。如下,我略微修改并注释:

# 安装和加载tidyverse包
install.packages("tidyverse")
library(tidyverse)

# 生成测试数据
df=data.frame(
  Phylum=c("Ruminococcaceae","Bacteroidaceae","Eubacteriaceae","Lachnospiraceae","Porphyromonadaceae"),
  GroupA=c(37.7397,31.34317,222.08827,5.08956,3.7393),
  GroupB=c(113.2191,94.02951,66.26481,15.26868,11.2179)
)

# 计算连线起始点Y轴坐标,即累计丰度的值
link_dat <- df %>%
  arrange(by=desc(Phylum)) %>%
  mutate(GroupA=cumsum(GroupA), GroupB=cumsum(GroupB))

# 数据格式转换,宽表格转换为ggplot2使用的长表格
df.long <- df %>% gather(group, abundance, -Phylum)
## 或者使用reshape2的melt函数
## df.long <- reshape2::melt(df, value.name='abundance', variable.name='group')

# 绘图,堆叠柱状图+组间连线
ggplot(df.long, aes(x=group, y=abundance, fill=Phylum)) +
  geom_bar(stat = "identity", width=0.5, col='black')  +
  geom_segment(data=link_dat, aes(x=1.25, xend=1.75, y=GroupA, yend=GroupB))

有模板改参数我喜欢

即然有了画两组的模板,仔细读一读代码,改成三组的应该不难,代码如下:

# 画三个组间比较
library(reshape2)

# 读生一个测试数据宽表格
df=data.frame(
  Phylum=c("Ruminococcaceae","Bacteroidaceae","Eubacteriaceae","Lachnospiraceae","Porphyromonadaceae"),
  GroupA=c(37.7397,31.34317,222.08827,5.08956,3.7393),
  GroupB=c(113.2191,94.02951,66.26481,15.26868,11.2179),
  GroupC=c(123.2191,94.02951,46.26481,35.26868,1.2179)
)

# melt转换为长表格为ggplot2绘图通用格式
# geom_segment添加直线和曲线,arrange按门水平名称字母降序排列;cumsum先将数值累计,再用mutate取代;现在己有两组间的高度位置,再设置X轴位置1.25, 1.75, 和Y位置
ggplot(melt(df), aes(x=variable, y=value, fill=Phylum)) +
  geom_bar(stat = "identity", width=0.5, col='black')  + theme_classic()+
  geom_segment(data=df %>% arrange(by=desc(Phylum)) %>% mutate(GroupA=cumsum(GroupA)) %>% mutate(GroupB=cumsum(GroupB)), aes(x=1.25, xend=1.75, y=GroupA, yend=GroupB))+
  geom_segment(data=df %>% arrange(by=desc(Phylum)) %>% mutate(GroupB=cumsum(GroupB)) %>% mutate(GroupC=cumsum(GroupC)), aes(x=2.25, xend=2.75, y=GroupB, yend=GroupC))
# 添加theme_classic()修改主题样式,这个经典主题我更喜欢
# x和xend分别为起始和终止,1,2组间X值起始分别为1.25和1.75,2,3组间则为2.25和2.75

三组及以上的情况如何轻松搞定

如果有更多的组,按上面genome_segment逐个添加显示不方便,需要修改的东西也太多了,有没有更完美的解决方法呢?

李陈浩老师也给大家写好了通用代码,只需按格式添加数据即可

# 三组或更多组的画法,只需添加数据即可
library(tidyverse)

df <- data.frame(
  Phylum=c("Ruminococcaceae","Bacteroidaceae","Eubacteriaceae","Lachnospiraceae","Porphyromonadaceae"),
  GroupA=c(37.7397,31.34317,222.08827,5.08956,3.7393),
  GroupB=c(113.2191,94.02951,66.26481,15.26868,11.2179),
  GroupC=c(123.2191,94.02951,46.26481,35.26868,1.2179),
  GroupD=c(37.7397,31.34317,222.08827,5.08956,3.7393)
)

df.long <- df %>% gather(group, abundance, -Phylum)

## 组间连线数据:
## 假设第一列是Phylum
link_dat <- df %>%
  arrange(by=desc(Phylum)) %>%
  mutate_if(is.numeric, cumsum)
bar.width <- 0.7
link_dat <- link_dat[, c(1,2,rep(3:(ncol(link_dat)-1),each=2), ncol(link_dat))]
link_dat <- data.frame(y=t(matrix(t(link_dat[,-1]), nrow=2)))
link_dat$x.1 <- 1:(ncol(df)-2)+bar.width/2
link_dat$x.2 <- 1:(ncol(df)-2)+(1-bar.width/2)

ggplot(df.long, aes(x=group, y=abundance, fill=Phylum)) +
  geom_bar(stat = "identity", width=bar.width, col='black')  +
  geom_segment(data=link_dat,
               aes(x=x.1, xend=x.2, y=y.1, yend=y.2), inherit.aes = F)

四组示例(以上代码适合三组及三组以上的情况)

此图比较适合展示时间序列、梯度变化有规律的连续组。因为只能连接相临的组,需要大家想好谁与谁比较很重要。对于需要全部两两比较是无法实现的。

最后感谢万能的宏基因组微信讨论群,让我认识了大家,总在我有困难时,大家无私的帮助我。谢谢你们!

希望我也能尽快成长为小牛,有更多的能力帮忙他人。

往期精品(点击图片直达文字对应教程)

后台回复“生信宝典福利第一波”或点击阅读原文获取教程合集

 

(请备注姓名-学校/企业-职务等)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值