相关系数热图(下三角,带数值)

下载 R / Python 代码与数据(795 KB)

用颜色深浅与数值同时展示多个连续变量两两之间的 Pearson 相关系数,只画下三角以避免重复,色标以 0 为中心对称(−1~1)。

图与代码

code/R/main.R
suppressPackageStartupMessages(library(ggplot2))

d <- read.csv("data/mtcars.csv", encoding = "UTF-8")
vars <- names(d)
r <- cor(d, method = "pearson")
write.csv(r, "outputs/stats_r.csv")

# 只画下三角(不含对角线):行从第 2 个变量起、列到第 10 个变量止
g <- expand.grid(row = vars[-1], col = vars[-length(vars)], stringsAsFactors = FALSE)
g <- g[match(g$row, vars) > match(g$col, vars), ]
g$r <- mapply(function(a, b) r[a, b], g$row, g$col)
g$col <- factor(g$col, levels = vars[-length(vars)])
g$row <- factor(g$row, levels = rev(vars[-1]))
g$txt <- sprintf("%.2f", g$r)
g$txt_col <- ifelse(abs(g$r) >= 0.65, "white", "grey15")

p <- ggplot(g, aes(col, row, fill = r)) +
  geom_tile(colour = "white", linewidth = 0.6) +
  geom_text(aes(label = txt, colour = txt_col), size = 2.4) +
  scale_colour_identity() +
  scale_fill_gradient2(low = "#2166AC", mid = "white", high = "#B2182B", midpoint = 0, limits = c(-1, 1),
                       breaks = c(-1, -0.5, 0, 0.5, 1), name = "Pearson r") +
  coord_fixed() +
  labs(x = NULL, y = NULL) +
  theme_minimal(base_size = 12) +
  theme(panel.grid = element_blank(), legend.key.height = unit(0.7, "in"))

ggsave("outputs/figure_r.png", p, width = 6, height = 4.5, dpi = 300, bg = "white")

code/py/main.py
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap
import scienceplots  # noqa: F401

plt.style.use(["science", "no-latex"])
plt.rcParams["font.family"] = "sans-serif"

d = pd.read_csv("data/mtcars.csv")
vars_ = list(d.columns)
r = d.corr(method="pearson")
r.to_csv("outputs/stats_py.csv")

# 只画下三角(不含对角线):行从第 2 个变量起、列到第 10 个变量止
sub = r.iloc[1:, :-1].to_numpy()
k = sub.shape[0]
mask = np.triu(np.ones((k, k), dtype=bool), k=1)       # 上三角不画
data = np.ma.array(sub, mask=mask)
cmap = LinearSegmentedColormap.from_list("bwr_clean", ["#2166AC", "#FFFFFF", "#B2182B"])

fig, ax = plt.subplots(figsize=(6, 4.5))
im = ax.pcolormesh(data, cmap=cmap, vmin=-1, vmax=1, edgecolors="white", linewidth=0.6)
for i in range(k):
    for j in range(k):
        if not mask[i, j]:
            v = sub[i, j]
            ax.text(j + 0.5, i + 0.5, f"{v:.2f}", ha="center", va="center", fontsize=7,
                    color="white" if abs(v) >= 0.65 else "#262626")
ax.set_xlim(0, k)
ax.set_ylim(k, 0)
ax.set_aspect("equal")
ax.set_xticks(np.arange(k) + 0.5, vars_[:-1])
ax.set_yticks(np.arange(k) + 0.5, vars_[1:])
ax.tick_params(which="both", length=0)
for s in ax.spines.values():
    s.set_visible(False)
cb = fig.colorbar(im, ax=ax, shrink=0.7, ticks=[-1, -0.5, 0, 0.5, 1], pad=0.03)
cb.set_label("Pearson r")
cb.outline.set_visible(False)
cb.ax.tick_params(which="both", length=0)
fig.savefig("outputs/figure_py.png", dpi=300, facecolor="white")

什么时候用

  • 在建模前快速浏览多个变量之间的相关结构,发现高度相关(共线)的变量
  • 在变量数不多(十几个以内)时同时展示相关方向、强弱与具体数值
  • 作为探索性分析的第一步,决定哪些变量值得进一步画散点图

常见误用

  • 相关不等于因果;相关系数大也可能由共同的第三个变量(混杂)造成
  • Pearson 相关只度量线性关系,对离群点敏感,且不能反映非线性关系;应配合散点图查看
  • 本例中 cyl、gear、carb 是计数或有序变量,vs、am 是 0/1 二分类变量。二分类变量与连续变量的 Pearson 相关即点二列相关,两个 0/1 变量之间即 φ 系数,数值本身可以计算,但其取值范围受类别比例限制,不宜与连续变量之间的相关系数直接比较大小;计数或有序变量可另用 Spearman 秩相关做敏感性对照
  • 样本量只有 32,相关系数的置信区间很宽;热图未做多重比较校正,也没有显示显著性,数值本身不能代替推断

数据与下载

数据:R 内置数据集 mtcars(datasets 包)(R 内置数据集(随 R 分发,GPL-2 | GPL-3))。32 款汽车的 11 个数值变量(mpg、cyl、disp、hp、drat、wt、qsec、vs、am、gear、carb)。计算两两 Pearson 相关系数,仅画下三角(不含对角线)。

下载 R / Python 代码与数据(795 KB)

下载包 sha256:0af6ad5e35346f99faf3faefd35c00d70e23329da73dc50125344cdd1552b730