百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

跟着iMeta学做图|ggplot2绘制相关性分析线面组合热图

bigegpt 2024-09-27 00:36 4 浏览

本文代码已经上传至https://github.com/iMetaScience/iMetaPlot230118corr 如果你使用本代码,请引用:Changchao Li. 2023. Destabilized microbial networks with distinct performances of abundant and rare biospheres in maintaining networks under increasing salinity stress. iMeta 1: e79. https://doi.org/10.1002/imt2.79

代码编写及注释:农心生信工作室

写在前面

相关性热图 (Correlation Heatmap) 的使用在微生物组研究中非常普遍,尤其是线面组合的相关性热图,其中的相关性热图通常表示环境因子间的Pearson相关系数,连线则表示物种组成与各环境因子的Mantel相关性。本期我们挑选2023年1月9日刊登在iMeta上的Destabilized microbial networks with distinct performances of abundant and rare biospheres in maintaining networks under increasing salinity stress,选择文章的Figure 1C进行复现,讲解和探讨如何基于ggplot2绘制线面组合的相关性热图,先上原图:

接下来,我们将通过详尽的代码逐步拆解原图,最终实现对原图的复现。

R包检测和安装

01

安装核心R包ggplot2以及一些功能辅助性R包,并载入所有R包。

options(repos = list(CRAN = "https://mirrors.tuna.tsinghua.edu.cn/CRAN/"))
if (!require("ggplot2"))
  install.packages('ggplot2') 
if (!require("vegan"))
  install.packages('vegan')
if (!require("tidyverse"))
  install.packages('tidyverse') 
if (!require("BiocManager"))
  install.packages('BiocManager') 
if (!require("ComplexHeatmap"))
  BiocManager::install('ComplexHeatmap')
# 检查开发者工具devtools,如没有则安装
if (!require("devtools"))
  install.packages("devtools")
# 加载开发者工具devtools
library(devtools)
# 检查linkET包,没有则通过github安装最新版
if (!require("linkET"))
  install_github("Hy4m/linkET", force = TRUE)
# 加载包
library(ggplot2)
library(vegan)
library(linkET)
library(tidyverse)
library(ComplexHeatmap)

读取数据及数据处理

02

绘制线面组合相关性热图,需要环境因子数据和物种组成数据。示例数据可在GitHub上获取。

#读取数据
#根据原文附表S1,获得样品的物理化学特性和地理分布情况,作为环境因子表
env <- read.csv("env.CSV",row.names = 1,header = T)
#生成一个物种组成的丰度表,行为样本,列为物种,行数必须与环境因子表的行数相同
spec <- read.csv("spec.CSV",row.names = 1,header = T)

03

计算环境因子的pearson相关系数,并根据绘图需求对数据进行处理。

corM <- cor(env,method = "pearson")#计算相关系数矩阵
#因为需要绘制的是上三角热图,需对矩阵进行处理,保留对角线及一半的数据即可
ncr <- nrow(corM)
for (i in 1:ncr){
  for (j in 1:ncr){
    if (j>i){
      corM[i,j] <- NA
    }
  }
}


corM <- as.data.frame(corM)%>%mutate(colID = rownames(corM))


#宽表转长表
corM_long <- pivot_longer(corM,cols = -"colID",names_to = "env",values_to = "cor")%>%na.omit()


#根据原图,固定x轴和y轴的顺序
corM_long$colID <- factor(corM_long$colID,levels = rownames(corM))
corM_long$env <- factor(corM_long$env,levels = rev(rownames(corM)))

绘图预览

04

使用ggplot2包绘制一个简单的上三角相关性热图:

p <- ggplot(corM_long)+
  geom_tile(aes(colID,env),fill = "white",color = "grey")+ #添加方框
  geom_point(aes(colID,env,size = abs(cor),color = cor)) #添加散点

05

对相关性热图进行美化:

col_fun <- colorRampPalette(c("#FFC107","white","#3F51B5"))(50) #设置渐变色
p <- ggplot(corM_long)+
  geom_tile(aes(colID,env),fill = "white",color = "grey")+ #添加方框
  geom_point(aes(colID,env,size = abs(cor),fill = cor),color = "black",shape = 21)+ #添加散点
  scale_x_discrete(position = "top")+ #x轴移动到顶部
  scale_y_discrete(position = "right")+ #y轴移动到右侧
  scale_size_continuous(range = c(1,10))+
  scale_fill_gradientn(colours = col_fun)+ #渐变色设置
  theme(axis.ticks = element_blank(),
        axis.title = element_blank(),
        panel.background = element_blank())+ #去除背景
  guides(size = "none",  #隐藏size图例
         fill = guide_colorbar(title = "Pearson's r"))  #修改fill图例标题

08

用Mantel test检验物种组成和不同环境因子之间的相关性。这里可以使用linkET包中的mantel_test()函数轻松完成检验:

mantel <- mantel_test(spec = spec,env = env)
#spec参数后是物种组成数据,env参数后是环境因子数据

07

生成绘制连接弧线所需的数据框。包括连线的起点和终点坐标,根据mantel r的值确定线条粗细,mantel p的值确定线条颜色:

n = nrow(corM)
curve_df <- data.frame(
  x0 = rep(-1,n),
  y0 = rep(6,n),
  x1 = c(0:(n-1)-0.1),
  y1 = c(n:1)
)%>%cbind(mantel)%>%
  mutate(
    line_col = ifelse(p <= 0.001, '#D1C4E9', NA),  #根据p值不同设置连接曲线的颜色不同
    line_col = ifelse(p > 0.001 & p <=  0.01, '#607D8B', line_col),
    line_col = ifelse(p > 0.01 & p <=  0.05, '#FF5722', line_col),
    line_col = ifelse(p > 0.05, '#4CAF50', line_col),
    linewidth = ifelse(r >=  0.4, 4, NA),
    # 根据r值不同设置连接曲线的宽度不同
    linewidth = ifelse(r >=  0.2 & r < 0.4, 2, linewidth),
    linewidth = ifelse(r < 0.2, 0.8, linewidth)
  )

08

绘制带有连线的相关性热图:

p <- ggplot(corM_long)+
  geom_tile(aes(colID,env),fill = "white",color = "grey")+ #添加方框
  geom_point(aes(colID,env,size = abs(cor),fill = cor),color = "black",shape = 21)+ #添加散点
  scale_x_discrete(position = "top")+ #x轴移动到顶部
  scale_y_discrete(position = "right")+ #y轴移动到右侧
  scale_size_continuous(range = c(1,10))+
  scale_fill_gradientn(colours = col_fun)+ #渐变色设置
  theme(axis.ticks = element_blank(),
        axis.title = element_blank(),
        panel.background = element_blank())+ #去除背景
  guides(size = "none",  #隐藏size图例
         fill = guide_colorbar(title = "Pearson's r"))+  #修改fill图例标题
  geom_curve(data = curve_df,aes(x = x0,y = y0,xend = x1,yend = y1), #根据起点终点绘制弧线
             size = curve_df$linewidth, #根据r值设置线条宽度
             color = curve_df$line_col,  #根据p值设置线条颜色
             curvature = 0.2)+ #设置弧度
  geom_point(data = curve_df,aes(x = x1,y = y1),size = 3,color = "red") #添加连线终点的点

09

我们发现,目前的图形缺少连线颜色和粗细的图例。为此,我们利用顾祖光博士开发的ComplexHeatmap包(关于ComplexHeatmap包的使用,可以参考往期推文跟着iMeta学做图|ComplexHeatmap绘制多样的热图),绘制一个单独的图例,并置于画布的左下方:

pdf("fig5.pdf",width = 10.04, height = 6.26)
grid.newpage()
#重新创建一个1行1列的布局
pushViewport(viewport(layout = grid.layout(nrow = 1, ncol = 1)))
vp_value <- function(row, col){
  viewport(layout.pos.row = row, layout.pos.col = col)
} 
p1 <- ggplot(corM_long)+
  geom_tile(aes(colID,env),fill = "white",color = "grey")+ #添加方框
  geom_point(aes(colID,env,size = abs(cor),fill = cor),color = "black",shape = 21)+ #添加散点
  scale_x_discrete(position = "top")+ #x轴移动到顶部
  scale_y_discrete(position = "right")+ #y轴移动到右侧
  scale_size_continuous(range = c(1,10))+
  scale_fill_gradientn(colours = col_fun)+ #渐变色设置
  theme(axis.ticks = element_blank(),
        axis.title = element_blank(),
        panel.background = element_blank())+ #去除背景
  guides(size = "none",  #隐藏size图例
         fill = guide_colorbar(title = "Pearson's r"))+  #修改fill图例标题
  geom_curve(data = curve_df,aes(x = x0,y = y0,xend = x1,yend = y1), #根据起点终点绘制弧线
             size = curve_df$linewidth, #根据r值设置线条宽度
             color = curve_df$line_col,  #根据p值设置线条颜色
             curvature = 0.2)+ #设置弧度
  geom_point(data = curve_df,aes(x = x1,y = y1),size = 3,color = "red") #添加连线终点的点
#将图p1添加进画布
print(p1,vp = vp_value(row = 1, col = 1))


#利用ComplexHeatmap的Legend()函数绘制单独的图例
#绘制Mantel's p图例
lgd1 = Legend(at = 1:4, legend_gp = gpar(fill = c('#D1C4E9','#607D8B','#FF5722','#4CAF50')), 
              title = "Mantel's p",
              labels  = c("≤ 0.001","0.001 - 0.01","0.01 - 0.05","> 0.05"),
              nr = 1)
#绘制Mantel's r图例
lgd2 = Legend(labels  = c("< 0.02","0.02 - 0.04","≥ 0.04"),
              title = "Mantel's r",
              #graphics参数自定义图例的高度
              graphics = list(
                function(x, y, w, h) grid.rect(x, y, w, h*0.1*0.8, gp = gpar(fill = "black")),
                function(x, y, w, h) grid.rect(x, y, w, h*0.1*2, gp = gpar(fill = "black")),
                function(x, y, w, h) grid.rect(x, y, w, h*0.1*4, gp = gpar(fill = "black"))
              ),nr = 1)
lgd = packLegend(lgd1, lgd2)


#将图例添加进相关性热图中
draw(lgd, x = unit(45, "mm"), y = unit(5, "mm"), just = c( "bottom"))
dev.off()
#> quartz_off_screen 
#>                 2

完整代码

if (!require("ggplot2"))
  install.packages('ggplot2') 
if (!require("vegan"))
  install.packages('vegan')
if (!require("tidyverse"))
  install.packages('tidyverse') 
if (!require("BiocManager"))
  install.packages('BiocManager') 
if (!require("ComplexHeatmap"))
  BiocManager::install('ComplexHeatmap')
# 检查开发者工具devtools,如没有则安装
if (!require("devtools"))
  install.packages("devtools")
# 加载开发者工具devtools
library(devtools)
# 检查linkET包,没有则通过github安装最新版
if (!require("linkET"))
  install_github("Hy4m/linkET", force = TRUE)
# 加载包
library(ggplot2)
library(vegan)
library(linkET)
library(tidyverse)
library(ComplexHeatmap)
#读取数据
#根据原文附表S1,获得样品的物理化学特性和地理分布情况,作为环境因子表
env <- read.csv("env.CSV",row.names = 1,header = T)
#生成一个物种组成的丰度表,行为样本,列为物种,行数必须与环境因子表的行数相同
spec <- read.csv("spec.CSV",row.names = 1,header = T)


corM <- cor(env,method = "pearson")#计算相关系数矩阵
#因为需要绘制的是上三角热图,需对矩阵进行处理,保留对角线及一半的数据即可
ncr <- nrow(corM)
for (i in 1:ncr){
  for (j in 1:ncr){
    if (j>i){
      corM[i,j] <- NA
    }
  }
}


corM <- as.data.frame(corM)%>%mutate(colID = rownames(corM))


#宽表转长表
corM_long <- pivot_longer(corM,cols = -"colID",names_to = "env",values_to = "cor")%>%na.omit()


#根据原图,固定x轴和y轴的顺序
corM_long$colID <- factor(corM_long$colID,levels = rownames(corM))
corM_long$env <- factor(corM_long$env,levels = rev(rownames(corM)))


mantel <- mantel_test(spec = spec,env = env)
#spec参数后是物种组成数据,env参数后是环境因子数据
n = nrow(corM)
curve_df <- data.frame(
  x0 = rep(-1,n),
  y0 = rep(6,n),
  x1 = c(0:(n-1)-0.1),
  y1 = c(n:1)
)%>%cbind(mantel)%>%
  mutate(
    line_col = ifelse(p <=  0.001, '#D1C4E9', NA),  #根据p值不同设置连接曲线的颜色不同
    line_col = ifelse(p > 0.001 & p <=  0.01, '#607D8B', line_col),
    line_col = ifelse(p > 0.01 & p <=  0.05, '#FF5722', line_col),
    line_col = ifelse(p > 0.05, '#4CAF50', line_col),
    linewidth = ifelse(r >=  0.4, 4, NA),
    # 根据r值不同设置连接曲线的宽度不同
    linewidth = ifelse(r >=  0.2 & r < 0.4, 2, linewidth),
    linewidth = ifelse(r < 0.2, 0.8, linewidth)
  )


pdf("Figure1A.pdf",width = 10.04, height = 6.26)
grid.newpage()
#重新创建一个1行1列的布局
pushViewport(viewport(layout = grid.layout(nrow = 1, ncol = 1)))
vp_value <- function(row, col){
  viewport(layout.pos.row = row, layout.pos.col = col)
} 
p1 <- ggplot(corM_long)+
  geom_tile(aes(colID,env),fill = "white",color = "grey")+ #添加方框
  geom_point(aes(colID,env,size = abs(cor),fill = cor),color = "black",shape = 21)+ #添加散点
  scale_x_discrete(position = "top")+ #x轴移动到顶部
  scale_y_discrete(position = "right")+ #y轴移动到右侧
  scale_size_continuous(range = c(1,10))+
  scale_fill_gradientn(colours = col_fun)+ #渐变色设置
  theme(axis.ticks = element_blank(),
        axis.title = element_blank(),
        panel.background = element_blank())+ #去除背景
  guides(size = "none",  #隐藏size图例
         fill = guide_colorbar(title = "Pearson's r"))+  #修改fill图例标题
  geom_curve(data = curve_df,aes(x = x0,y = y0,xend = x1,yend = y1), #根据起点终点绘制弧线
             size = curve_df$linewidth, #根据r值设置线条宽度
             color = curve_df$line_col,  #根据p值设置线条颜色
             curvature = 0.2)+ #设置弧度
  geom_point(data = curve_df,aes(x = x1,y = y1),size = 3,color = "red") #添加连线终点的点
#将图p1添加进画布
print(p1,vp = vp_value(row = 1, col = 1))


#利用ComplexHeatmap的Legend()函数绘制单独的图例
#绘制Mantel's p图例
lgd1 = Legend(at = 1:4, legend_gp = gpar(fill = c('#D1C4E9','#607D8B','#FF5722','#4CAF50')), 
              title = "Mantel's p",
              labels  = c("≤ 0.001","0.001 - 0.01","0.01 - 0.05","> 0.05"),
              nr = 1)
#绘制Mantel's r图例
lgd2 = Legend(labels  = c("< 0.02","0.02 - 0.04","≥ 0.04"),
              title = "Mantel's r",
              #graphics参数自定义图例的高度
              graphics = list(
                function(x, y, w, h) grid.rect(x, y, w, h*0.1*0.8, gp = gpar(fill = "black")),
                function(x, y, w, h) grid.rect(x, y, w, h*0.1*2, gp = gpar(fill = "black")),
                function(x, y, w, h) grid.rect(x, y, w, h*0.1*4, gp = gpar(fill = "black"))
              ),nr = 1)
lgd = packLegend(lgd1, lgd2)


#将图例添加进相关性热图中
draw(lgd, x = unit(45, "mm"), y = unit(5, "mm"), just = c( "bottom"))


dev.off()
#> quartz_off_screen 
#>                 2

以上数据和代码仅供大家参考,如有不完善之处,欢迎大家指正!

相关推荐

有些人能留在你的心里,但不能留在你生活里。

有时候,你必须要明白,有些人能留在你的心里,但不能留在你生活里。Sometimes,youhavetorealize,Somepeoplecanstayinyourheart,...

Python学不会来打我(34)python函数爬取百度图片_附源码

随着人工智能和大数据的发展,图像数据的获取变得越来越重要。作为Python初学者,掌握如何从网页中抓取图片并保存到本地是一项非常实用的技能。本文将手把手教你使用Python函数编写一个简单的百度图片...

软网推荐:图像变变变 一“软”见分晓

当我们仅需要改变一些图片的分辨率、裁减尺寸、添加水印、标注文本、更改图片颜色,或将一种图片转换为另一种格式时,总比较讨厌使用一些大型的图像处理软件,尤其是当尚未安装此类软件时,更是如此。实际上,只需一...

首款WP8.1图片搜索应用,搜照片得资料

首款WP8.1图片搜索应用,搜照片得资料出处:IT之家原创(天际)2014-11-1114:32:15评论WP之家报道,《反向图片搜索》(ReverseImageSearch)是Window...

分享一组美图(图片来自头条)(头条美女头像)

...

盗墓笔记电视剧精美海报 盗墓笔记电视剧全集高清种子下载

出身“老九门”世家的吴邪,因身为考古学家的父母在某次保护国家文物行动时被国外盗墓团伙杀害,吴家为保护吴邪安全将他送去德国读书,因而吴邪对“考古”事业有着与生俱来的兴趣。在一次护宝过程中他偶然获得一张...

微软调整Win11 24H2装机策略:6月起36款预装应用改为完整版

IT之家7月16日消息,微软公司今天(7月16日)发布公告,表示自今年6月更新开始,已默认更新Windows1124H2和WindowsServer2025系统中预装...

谷歌手把手教你成为谣言终结者 | 域外

刺猬公社出品,必属原创,严禁转载。合作事宜,请联系微信号:yunlugongby贾宸琰编译、整理11月23日,由谷歌新闻实验室(GoogleNewsLab)联合Bellingcat、DigD...

NAS 部署网盘资源搜索神器:全网资源一键搜,免费看剧听歌超爽!

还在为找不到想看的电影、电视剧、音乐而烦恼?还在各个网盘之间来回切换,浪费大量时间?今天就教你如何在NAS上部署aipan-netdisk-search,一款强大的网盘资源搜索神器,让你全网资源...

使用 Docker Compose 简化 INFINI Console 与 Easysearch 环境搭建

前言回顾在上一篇文章《搭建持久化的INFINIConsole与Easysearch容器环境》中,我们详细介绍了如何使用基础的dockerrun命令,手动启动和配置INFINICon...

为庆祝杜特尔特到访,这个国家宣布全国放假?

(观察者网讯)近日,一篇流传甚广的脸书推文称,为庆祝杜特尔特去年访问印度,印度宣布全国放假,并举办了街头集会以示欢迎。菲媒对此做出澄清,这则消息其实是“假新闻”。据《菲律宾世界日报》2日报道,该贴子...

一课译词:毛骨悚然(毛骨悚然的意思是?)

PhotobyMoosePhotosfromPexels“毛骨悚然”,汉语成语,意思是毛发竖起,脊梁骨发冷;形容恐惧惊骇的样子(withone'shairstandingonend...

Bing Overtakes Google in China&#39;s PC Search Market, Fueled by AI and Microsoft Ecosystem

ScreenshotofBingChinahomepageTMTPOST--Inastunningturnintheglobalsearchenginerace,Mic...

找图不求人!6个以图搜图的识图网站推荐

【本文由小黑盒作者@crystalz于03月08日发布,转载请标明出处!】前言以图搜图,专业说法叫“反向图片搜索引擎”,是专门用来搜索相似图片、原始图片或图片来源的方法。常用来寻找现有图片的原始发布出...

浏览器功能和“油管”有什么关联?为什么要下载

现在有没有一款插件可以实现全部的功能,同时占用又小呢,主题主要是网站的一个外观,而且插件则主要是实现wordpress网站的一些功能,它不仅仅可以定制网站的外观,还可以实现很多插件的功能,搭载chro...