# A tibble: 32 × 11
mpg cyl disp hp drat wt qsec vs am gear carb
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 21 6 160 110 3.9 2.62 16.5 0 1 4 4
2 21 6 160 110 3.9 2.88 17.0 0 1 4 4
3 22.8 4 108 93 3.85 2.32 18.6 1 1 4 1
4 21.4 6 258 110 3.08 3.22 19.4 1 0 3 1
5 18.7 8 360 175 3.15 3.44 17.0 0 0 3 2
6 18.1 6 225 105 2.76 3.46 20.2 1 0 3 1
7 14.3 8 360 245 3.21 3.57 15.8 0 0 3 4
8 24.4 4 147. 62 3.69 3.19 20 1 0 4 2
9 22.8 4 141. 95 3.92 3.15 22.9 1 0 4 2
10 19.2 6 168. 123 3.92 3.44 18.3 1 0 4 4
# ℹ 22 more rows
R语言如何绘制相关性图
前言
本篇是R语言ggplot2系列包手搓带聚类,条带的半相关性图。
什么是相关性图?
相关性是指两个或多个变量之间的关系或相互影响程度。若两组的值一起增大,我们称之为正相关,若一组的值增大时,另一组的值减小,我们称之为负相关。其值介于-1与1之间,即越接近1,越正相关;越接近-1,越负相关。
常见的有两种计算相关性的算法:皮尔逊相关性(pearson)和斯皮尔曼相关性(spearman)。皮尔逊相关性最常用,适合正态分布的数据。斯皮尔曼相关性是秩相关,不受极大极小值的影响。
在组学中的应用,例如,两个技术性重复实验的结果相关性很低,则说明数据有异常。
需要注意的地方,做样本之间的相关性的时候,蛋白之间要对应,不可随意打乱顺序。数据中有缺失值的情况,通常用”pairwise.complete.obs”算法处理缺失值,即两两配对删除缺失值。
相关性图就是,用图的形式展现出相关性的结果。

绘图前的数据准备
这里就用R语言自带的示例数据了,mtcars
R语言如何绘制相关性图
# 代码来源:https://www.r2omics.cn/
# 加载必需R包(若未安装,需先运行:install.packages(c("ggplot2", "dplyr", "scales", "aplot", "ggtree", "psych", "tibble", "tidyr", "openxlsx")))
library(ggplot2) # 核心绘图包,用于绘制热图、分组标签等
library(dplyr) # 数据处理包,用于筛选、排序、聚合等操作
library(scales) # 颜色缩放工具包(本代码未直接调用,但为相关性热图常用依赖)
library(aplot) # 图形组合包,实现多图拼接(上下/左右插入)
library(ggtree) # 聚类树绘制包,用于可视化层次聚类结果
library(psych) # 相关性分析包,提供corr.test函数计算相关系数和p值
library(tibble) # 数据框处理包,提供rownames_to_column等行名转列功能
library(tidyr) # 数据格式转换包,提供pivot_longer实现宽格式转长格式
library(openxlsx) # 文件保存包,用于将相关性矩阵导出为Excel
library(ggstyle) # 提供更多主题和配色方案devtools::install_github("sz-zyp/ggstyle")
# ===================== 1. 模拟数据(可替换为真实数据)=====================
set.seed(123) # 固定随机种子,确保每次运行生成相同模拟数据(结果可重复)
n <- 50 # 样本数量(数据框行数:50个样本)
var_num <- 10 # 变量数量(数据框列数:10个变量)
# 生成50行×10列的正态分布数据(均值0,标准差1)
df = mtcars
# 定义变量分组信息(10个变量分为2组:A组5个,B组5个)
dfGroup <- data.frame(
"Sample" = colnames(df), # 变量名(与df的列名一致,此处命名为Sample仅为方便后续绘图)
"Group" = c(rep("A", 5), rep("B", 6)) # 分组:前5个变量为A组,后5个为B组
)
# ===================== 2. 计算变量间相关性矩阵 =====================
ct <- psych::corr.test(
x = df, # 输入数据(行=样本,列=变量)
use = "pairwise", # 缺失值处理方式:成对删除(仅删除存在缺失值的成对观测)
method = "pearson", # 相关性计算方法:皮尔逊相关(适用于正态分布数据)
adjust = "BH", # p值矫正方法:Benjamini-Hochberg(控制假发现率)
ci = FALSE # 不计算相关系数的置信区间(简化输出)
)
# ct的核心输出(按需查看):
# ct$r:相关性系数矩阵(10×10,变量间两两相关系数)
# ct$p:原始p值矩阵(未矫正的显著性检验结果)
# ct$p.adj:矫正后的p值矩阵(BH矫正后,更稳健)
# ct$n:每个相关系数的有效样本量
# 提取相关性系数矩阵,转换为数据框格式
cor_matrix <- data.frame(ct$r)
# ===================== 3. 变量层次聚类(用于热图排序)=====================
# 计算变量间距离矩阵:1-相关系数(相关系数越近,距离越小)
row_dist <- dist(1 - cor_matrix)
# 层次聚类(默认方法:ward.D2,最小化组内方差)
row_clust <- hclust(row_dist)
# 绘制垂直聚类树(用于热图左侧显示)
pTreeY <- row_clust %>%
ggtree::ggtree(
layout = "rectangular", # 矩形布局(清晰展示聚类结构)
branch.length = "none" # 不显示分支长度(仅关注聚类顺序)
)
# + geom_tiplab(size=2) # 可选:添加聚类树叶节点标签(变量名)
# 提取聚类后的变量顺序(关键:用于后续热图的行列排序)
myOrder <- pTreeY$data %>%
arrange(angle) %>% # 按角度排序(ggtree内部排序逻辑,确保叶节点顺序正确)
filter(isTip) %>% # 筛选叶节点(仅保留变量对应的节点)
pull(label) # 提取叶节点标签(变量名),得到聚类后的顺序
# 绘制水平聚类树(用于热图顶部显示)
pTreeX <- pTreeY +
ggtree::layout_dendrogram() # 转换为水平布局(适配热图顶部位置)
# + geom_tiplab(size=2) # 可选:添加聚类树叶节点标签(变量名)
# ===================== 4. 相关性矩阵预处理(排序+上三角提取)=====================
# 按聚类结果重新排序相关性矩阵(行:逆序myOrder,列:myOrder,确保与聚类树匹配)
cor_matrix_ordered <- cor_matrix[rev(myOrder), myOrder]
# 生成上三角相关性矩阵(下三角设为NA,绘图时不显示,避免重复信息)
cor_matrix_upper <- cor_matrix[myOrder, myOrder] # 按聚类顺序排序原始相关矩阵
# lower.tri:标记下三角元素(diag=FALSE:不包含对角线),设为NA
cor_matrix_upper[lower.tri(cor_matrix_upper, diag = FALSE)] <- NA
# 转换为ggplot2所需的长格式数据(热图绘图要求)
cor_long <- cor_matrix_upper %>%
tibble::rownames_to_column("Var1") %>% # 行名(变量1)转为列Var1
pivot_longer(
-1, # 除Var1外的所有列(即变量2)
names_to = "Var2", # 列名转为Var2(变量2)
values_to = "Correlation", # 数值转为Correlation(相关系数)
values_drop_na = TRUE # 删除NA值(下三角部分,不绘图)
)
# 确保Var1和Var2为因子类型,并固定 levels 为聚类顺序(避免绘图时自动排序)
cor_long$Var1 <- factor(cor_long$Var1, levels = colnames(cor_matrix_ordered))
cor_long$Var2 <- factor(cor_long$Var2, levels = colnames(cor_matrix_ordered))
# 验证排序是否正确(可选)
# cor_long$Var1 %>% levels()
# cor_long$Var2 %>% levels()
# ===================== 5. 绘制核心图形组件 =====================
# 注意:需提前定义两个全局变量(用户代码遗漏,此处补充说明)
borderSize <- 0.2 # 热图单元格边框宽度(可自定义,如0.1~0.5)
myTextSize <- 8 # 坐标轴文字大小(可自定义,如6~10)
# 5.1 上三角相关性热图(核心图p1)
p1 <- ggplot(cor_long, aes(x = Var1, y = Var2, fill = Correlation)) +
geom_tile(
color = "white", # 单元格边框颜色(白色,分隔单元格)
size = borderSize, # 边框宽度(提前定义的borderSize)
na.rm = TRUE # 忽略NA值(不绘制下三角)
) +
# 双向颜色映射(适配相关系数[-1,1])
scale_fill_gradient2(
low = "#0001c3", # 负相关颜色(深蓝色)
mid = "white", # 无相关颜色(白色,midpoint=0)
high = "#cb0403", # 正相关颜色(深红色)
midpoint = 0, # 颜色中点(相关系数=0)
limit = c(-1, 1), # 颜色范围(覆盖所有相关系数)
space = "Lab", # 颜色空间(Lab空间颜色过渡更均匀)
name = "Cor" # 图例名称(相关系数)
) +
theme_void() + # 清除默认主题(无坐标轴、网格线等)
scale_y_discrete(position = "left") + # y轴标签放在左侧(与聚类树对齐)
theme(
axis.ticks = element_blank(), # 隐藏坐标轴刻度线
axis.title = element_blank(), # 隐藏坐标轴标题
panel.grid = element_blank(), # 隐藏网格线
axis.text.y = element_text( # 调整y轴文字(变量名)
size = myTextSize, # 文字大小(提前定义的myTextSize)
hjust = 1 # 文字右对齐(贴近热图)
)
)
# 5.2 顶部分组标签图(p2:显示变量分组A/B)
p2 <- ggplot(dfGroup) +
geom_tile(
aes(
x = factor(Sample, levels = rev(colnames(cor_matrix_ordered))), # x轴:变量(聚类逆序,与顶部聚类树匹配)
y = 1, # y轴固定为1(仅作为色块高度)
fill = Group # 按分组填充颜色
)
) +
theme_void() + # 清除默认主题
theme(
axis.ticks = element_blank(), # 隐藏刻度线
axis.title = element_blank(), # 隐藏标题
panel.grid = element_blank(), # 隐藏网格线
axis.text.x = element_text( # 调整x轴文字(变量名)
angle = 90, # 文字旋转90度(避免重叠)
hjust = 0, # 水平对齐(左对齐)
vjust = 0.5, # 垂直居中
size = myTextSize # 文字大小
)
)+
ggstyle::scale_fill_sci(palette = "Set2",modeColor = "1")
# 5.3 左侧分组标签图(p3:显示变量分组A/B)
p3 <- ggplot(dfGroup) +
geom_tile(
aes(
x = 1, # x轴固定为1(仅作为色块宽度)
y = factor(Sample, levels = colnames(cor_matrix_ordered)), # y轴:变量(聚类顺序,与左侧聚类树匹配)
fill = Group # 按分组填充颜色
)
)+
ggstyle::scale_fill_sci(palette = "Set2",modeColor = "1")
# 定义简化主题函数(统一清除冗余元素)
mythemeF <- function(p) {
p + theme_void() # 应用无坐标轴主题
}
# ===================== 6. 组合图形(两种组合方案)=====================
# 方案1:热图 + 顶部分组标签 + 左侧分组标签(无聚类树)
p <- mythemeF(p1) %>% # 给p1应用简化主题
aplot::insert_top((mythemeF(p2)), height = 0.05) %>% # 顶部插入p2,高度占比5%(避免标签过高)
aplot::insert_left(mythemeF(p3), width = 0.05) # 左侧插入p3,宽度占比5%(避免标签过宽)
p
# 方案2:完整组合(热图 + 聚类树 + 分组标签)
pAll <- (p1) %>%
aplot::insert_top((p2), height = 0.05) %>% # 顶部:分组标签(5%高度)
aplot::insert_left(mythemeF(p3), width = 0.05) %>% # 左侧:分组标签(5%宽度)
aplot::insert_top(pTreeX, height = 0.15) %>% # 顶部上方:水平聚类树(15%高度)
aplot::insert_left(pTreeY, width = 0.15) # 左侧左方:垂直聚类树(15%宽度)
pAll
# ===================== 7. 保存结果(文件输出)=====================
# 注意:需提前定义输出路径outPath1(示例:outPath1 <- "你的输出文件夹路径/")
# 保存排序后的相关性矩阵为Excel文件(含行名)
# openxlsx::write.xlsx(
# x = data.frame(cor_matrix_ordered, check.names = FALSE), # 保留原始列名(不自动修改特殊字符)
# file = file.path("sampleCor.xlsx"), # 输出文件路径+名称
# rowNames = TRUE # 保留行名(变量名)
# )
# 保存方案1图形(无聚类树)
# ggsave(
# filename = file.path("样本相关性图.png"), # 图片路径+名称
# plot = p, # 待保存图形
# width = 10, # 图片宽度(英寸)
# height = 8, # 图片高度(英寸)
# dpi = 300 # 分辨率(300dpi,高清)
# )
#
# # 保存方案2图形(带聚类树和分组标签)
# ggsave(
# filename = file.path("样本相关性图_带聚类树和名字.png"), # 图片路径+名称
# plot = pAll, # 待保存图形
# width = 10, # 图片宽度
# height = 8, # 图片高度
# dpi = 300 # 分辨率
# )