R 数据可视化 —— 相关系数图

一、ggplot 相关系数图

前言

相关系数图是对相关系数矩阵进行可视化的,用于展示多组变量之间的相关性。

根据数据的分布特征,可以应用不同的相关系数计算方法,如 pearsonspearmanKendall

相关系数矩阵的可视化图形,可以是热图、气泡图、方块图、椭圆图,也可以是纯数字文本形式,等等。

下面我们介绍它们的绘制方法

示例

我们首先使用 ggplot2 包提供的函数来绘制这些图形

先计算相关系数矩阵

mat <- as.data.frame(round(cor(mtcars), 2))
mat$var1 <- rownames(mat)
data <- gather(mat, key = "var2", value = "corr", -var1)

1. 热图

library(RColorBrewer)
# 获取 5 个颜色
my_color <- brewer.pal(5, "Spectral")

ggplot(data, aes(var1, var2, fill = corr)) +
  geom_tile(colour = "black") +
  scale_fill_gradientn(colours = my_color)

2. 气泡图

ggplot(data, aes(var1, var2, fill = corr)) +
  geom_point(aes(size = abs(corr)), shape = 21, colour = "black") +
  scale_fill_gradientn(colours = my_color) +
  scale_size_area(max_size = 15, guide = FALSE)

3. 方块图

只要设置参数 shape = 22,就可以换成方块了

geom_point(aes(size = abs(corr)), shape = 22, colour = "black") 

4. 设置标签

使用 geom_text 添加标签

geom_text(aes(label = corr), size = 3, colour = "black", alpha = 0.7)

为正负相关设置不同的颜色

geom_point(aes(fill = corr > 0, size = corr), shape = 21)

5. 混合绘图

如果想绘制上三角或下三角该怎么做?

ggplot2 并没有提供相应的操作,但是我们可以手动对数据进行处理,将对应的数据赋值为 NA

比如,我想绘制下三角。首先,把上三角赋值为 NA

mat <- as.data.frame(round(cor(mtcars), 2))

for (i in 1:10) {
  for (j in (i+1):11) {
    mat[i,j] <- NA
  }
}

然后将变量名的顺序固定为行名顺序

mat$var1 <- rownames(mat)
data <- gather(mat, key = "var2", value = "corr", -var1) %>%
  mutate(var1 = factor(var1, levels = rownames(mat)),
         var2 = factor(var2, levels = rownames(mat)))

然后绘制图形

my_color <- brewer.pal(5, "Spectral")

ggplot(data, aes(var1, var2)) +
  geom_point(aes(fill = corr, size = corr), shape = 21) +
  geom_text(aes(label = corr), size = 3, colour = "white") +
  scale_fill_gradientn(colours = my_color) +
  scale_size_area(max_size = 15, guide = FALSE) +
  theme(legend.position = "none")

如果想将文本和形状分别绘制在上三角和下三角,操作也是类似的,只是要多添加一个上三角矩阵。

mat1 <- as.data.frame(round(cor(mtcars), 2))

for (i in 1:10) {
  for (j in (i+1):11) {
    mat1[i,j] <- NA
  }
}

mat2 <- as.data.frame(round(cor(mtcars), 2))

for (i in 1:11) {
  for (j in 1:i) {
    mat2[i,j] <- NA
  }
}


mat1$var1 <- rownames(mat1)
data1 <- gather(mat1, key = "var2", value = "corr", -var1) %>%
  mutate(var1 = factor(var1, levels = rownames(mat1)),
         var2 = factor(var2, levels = rownames(mat1)))

mat2$var1 <- rownames(mat2)
data2 <- gather(mat2, key = "var2", value = "corr", -var1) %>%
  mutate(var1 = factor(var1, levels = rownames(mat2)),
         var2 = factor(var2, levels = rownames(mat2)))

my_color <- brewer.pal(5, "Spectral")

ggplot(data1, aes(var1, var2)) +
  geom_point(aes(fill = corr, size = corr), shape = 21) +
  geom_text(data = data2, aes(label = corr, colour = corr), size = 5) +
  scale_fill_gradientn(colours = my_color) +
  scale_colour_gradientn(colours = my_color) +
  scale_size_area(max_size = 15, guide = FALSE) +
  theme(legend.position = "none")

如果要将对角线换成变量名,也很简单

mat1 <- as.data.frame(round(cor(mtcars), 2))

for (i in 1:11) {
  for (j in i:11) {
    mat1[i,j] <- NA
  }
}

mat2 <- as.data.frame(round(cor(mtcars), 2))

for (i in 1:11) {
  for (j in 1:i) {
    mat2[i,j] <- NA
  }
}

var_name <- data1 %>% 
  filter(var1 == var2)

mat1$var1 <- rownames(mat1)
data1 <- gather(mat1, key = "var2", value = "corr", -var1) %>%
  mutate(var1 = factor(var1, levels = rownames(mat1)),
         var2 = factor(var2, levels = rownames(mat1)))

mat2$var1 <- rownames(mat2)
data2 <- gather(mat2, key = "var2", value = "corr", -var1) %>%
  mutate(var1 = factor(var1, levels = rownames(mat2)),
         var2 = factor(var2, levels = rownames(mat2)))

my_color <- brewer.pal(5, "Spectral")

ggplot(data1, aes(var1, var2)) +
  geom_point(aes(fill = corr, size = corr), shape = 21) +
  #geom_point(data = data2, aes(fill = corr, size = corr), shape = 23) +
  geom_text(data = data2, aes(label = corr, colour = corr), size = 5) +
  geom_text(data = var_name, aes(label = var1), size = 5) +
  scale_fill_gradientn(colours = my_color) +
  scale_colour_gradientn(colours = my_color) +
  scale_size_area(max_size = 15, guide = FALSE) +
  scale_x_discrete(position = 't') +
  theme(
    legend.position = "none",
    axis.title = element_blank()
    )

方块配圆形

geom_point(data = data2, aes(fill = corr, size = corr), shape = 22) +
# geom_text(data = data2, aes(label = corr, colour = corr), size = 5) +

热图配圆形

ggplot(data1, aes(var1, var2)) +
  geom_tile(data = data2, aes(fill = corr), na.rm = TRUE) +
  geom_text(data = data2, aes(label = corr), colour = "black", size = 5) +
  geom_point(aes(fill = corr, size = corr), shape = 21) +
  geom_text(data = var_name, aes(label = var1), size = 5) +
  scale_fill_gradientn(colours = my_color, na.value = "white") +
  scale_colour_gradientn(colours = my_color) +
  scale_size_area(max_size = 15, guide = FALSE) +
  scale_x_discrete(position = 't') +
  theme(
    panel.background = element_blank(),
    legend.position = "none",
    axis.title = element_blank()
    )

注意,需要将 geom_tile 放在最前面,同时设置 na.value 参数的值

代码:https://github.com/dxsbiocc/learn/blob/main/R/plot/corr_plot.R

总结一下,其实用 ggplot2 做个性化绘图没那么难,重要的是理解其中的原理。

二、corrplot 相关系数图

前言

前面,我们介绍了如何使用 ggplot2 来绘制相关系数图,这节,我们将介绍用 corrplot 包绘制相关系数图

corrplot 主要用于图形化展示相关系数矩阵、置信区间,同时还包含一些矩阵排序算法。同时能够以简单的方式,选择颜色、文本标签和布局等

安装导入

if (!require(corrplot)) {
  install.packages("corrplot")
}

library(corrplot)

可视化方法

corrplot 包含 7 种可视化方法,可使用 method 参数来进行选择,参数值如下

  1. circle:圆形
mat <- cor(mtcars)

corrplot(mat, method = "circle")
  1. square:方形
corrplot(mat, method = "square")
  1. ellipse:椭圆
corrplot(mat, method = "ellipse")
  1. number:数值
corrplot(mat, method = "number")
  1. shade:阴影
corrplot(mat, method = "shade")
  1. color:热图
corrplot(mat, method = "color")
  1. pie:饼图
corrplot(mat, method = "pie")

默认情况下,使用红蓝两种颜色,正相关显示为蓝色,负相关为红色,颜色的强度和图形的大小与相关性成正比

布局方式

corrplot 有三种布局方式,通过 type 参数设置

  1. full: 默认值,绘制整个相关系数矩阵
  2. upper: 绘制上三角矩阵
  3. lower: 绘制下三角矩阵

例如,上三角

corrplot(mat, method = "circle", type = "upper")

下三角

corrplot(mat, method = "circle", type = "lower")

那如何将不同图形混合绘制呢?

corrplot 提供了一个封装函数 corrplot.mixed,用于绘制混合图形

该函数通过 lower, upper 两个参数指定上下三角的类型,例如

corrplot.mixed(mat)

默认绘制上三角为圆形下三角为数字的图形

设置对角线标签放置的位置 tl.pos 和对角线图像类型 diag

tl.pos 可以是 ltdn,分别表示放在左侧、对角线或不显示

diag 可以是 uln 分别表示与上、下三角一致或不绘制

corrplot.mixed(mat, tl.pos = "lt", diag = 'l')

设置颜色,其中 tl.col 为对角线标签颜色,lower.colupper.col 分别表示上、下三角的颜色

library(RColorBrewer)

corrplot.mixed(mat, lower = "ellipse", upper = "circle", tl.col = "black",
               lower.col = brewer.pal(5, "Spectral"), 
               upper.col = brewer.pal(5, "Set2"))

矩阵重排

我们可以根据相关系数对矩阵进行重排,从矩阵中找到隐藏的结构和模式。

corrplot4 种排序方法,通过 order 参数设置:

  • AOE:特征向量的角度顺序
  • FPC:第一主成分顺序
  • hclust:层次聚类的顺序,可以使用 hclust.method 参数设置距离度量方法
  • alphabet:字母表顺序
corrplot(mat, order = "AOE")
corrplot(mat, order = "hclust")

对于 hclust 方式,可以为聚类结果绘制矩形,使用 addrect 参数来指定需要绘制矩形的数量

corrplot(mat, order = "hclust", hclust.method = "median", addrect = 3)

根据聚类结果,将颜色设置为 3 种,同时更改背景色

corrplot(mat, order = "hclust", hclust.method = "median", addrect = 3,
         col = brewer.pal(3, "Set1"), bg = brewer.pal(7, "Set2")[7])

设置文本标签及图例

cl.* 参数是设置颜色图例的参数,tl.* 是设置文本图例的参数

例如,tl.coltl.srt 用来设置文本标签的颜色和旋转

corrplot(mat, order = "FPC", cl.pos = "b", tl.srt = 45)
corrplot(mat, order = "FPC", cl.ratio = 0.2, cl.align = "l")
corrplot(mat, order = "hclust", type = "lower", 
         tl.pos = 'd', tl.cex = 1.25, tl.srt = 45, tl.col = "black")

缺失值处理

默认情况下,corrplot 会将 NA 值渲染为 ? 可以使用 na.label 参数设置 NA 值的显示

mat2 <- mat
diag(mat2) <- NA

corrplot(mat2)
corrplot(mat2, na.label = "*")

plotmath 表达式

可以在文本标签前面加上 :=$ 字符前缀,来激活 plotmath 表达式渲染

mat2 <- mat[1:5,1:5]
colnames(mat2) <- c("alpha", "beta", ":alpha+beta", ":a[0]", "=a[beta]")
rownames(mat2) <- c("alpha", "beta", NA, "$a[0]", "$ a[beta]")

corrplot(mat2)

添加显著性检验

我们还可以在图像中添加显著性信息。首先,使用 cor.mtest 计算显著性 p 值和置信区间

> pmat <- cor.mtest(mtcars, conf.level = .95)
> str(pmat)
List of 3
 $ p    : num [1:11, 1:11] 0.00 6.11e-10 9.38e-10 1.79e-07 1.78e-05 ...
 $ lowCI: num [1:11, 1:11] 1 -0.926 -0.923 -0.885 0.436 ...
 $ uppCI: num [1:11, 1:11] 1 -0.716 -0.708 -0.586 0.832 ...

然后将计算结果中的 p 值传递给 p.mat 参数,同时设置显著性水平 sig.level,高于该值的相关系数被认为是不显著的

corrplot(mat, p.mat = pmat$p, sig.level = 0.05)

可以看到,不显著的相关系数被画 了,我们可以设置 insig = "blank" 不显示不显著的点

corrplot(mat, p.mat = pmat$p, sig.level = 0.05,
         insig = "blank")

insig 参数还支持其他值

  • pch: 默认值

  • p-value: 显示 p 值

  • n: 不做任何操作

  • label_sig: 用 * 来表示显著性

搭配 sig.level 使用,按照等级绘制多个 *

corrplot(mat, p.mat = pmat$p, sig.level = c(.001, .01, .05),
         insig = "label_sig", pch.cex = 0.9, pch.col = "white")

pch 参数可以设置显著的点的显示文本

corrplot(mat, p.mat = pmat$p, sig.level = 0.05, pch = "p < 0.05",
         insig = "label_sig", pch.cex = 0.7, pch.col = "white")

显示置信区间

根据上一步计算出的置信上下限,我们可以展示变量之间的置信区间

使用 lowCI.matuppCI.mat 来设置置信区间的上下限,使用 plotCI 参数来设置显示的图形,支持 n(不显示), square, circle, rect 四种类型

corrplot(mat, lowCI.mat = pmat$lowCI, uppCI.mat = pmat$uppCI,
         order = "hclust", plotCI = "rect", cl.pos = "n")

最后,需要说明的一点是,该包不只是针对相关系数矩阵,也可以绘制其他类型的矩阵

例如

ran <- round(matrix(runif(225, -100,100), 15))
corrplot(ran, is.corr = FALSE, method = "ellipse", cl.lim = c(-100, 100))

如果行列数不一致,可以使用 win.asp 参数将图形调整为正方形

ran <- matrix(rnorm(70), ncol = 7)
corrplot(ran, is.corr = FALSE, win.asp = .7, method = "circle")
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容