autoplot(ggplot)从prcomp获取得分与载荷的原理及手动实现方法
手动实现带载荷的PCA可视化(替代autoplot)
要理解autoplot(来自ggfortify包)如何关联样本得分与载荷向量,核心是它对载荷做了匹配得分尺度的缩放,有时还会对得分和载荷做标准化处理。下面一步步拆解逻辑并实现自定义绘图:
1. 明确prcomp的核心输出
prcomp返回的对象包含三个关键部分:
m1$x:样本得分矩阵(标准化后的原始数据 × 旋转矩阵,范围约-2.5到3)m1$rotation:载荷矩阵(变量在主成分上的权重,范围约-1到1)m1$sdev:各主成分的标准差(反映该PC的方差大小)
2. 还原autoplot的载荷缩放逻辑
autoplot默认会做以下两步转换(对应scale.axes = TRUE):
- 先将载荷矩阵乘以对应PC的标准差,让载荷的尺度与得分匹配
- 对得分和载荷矩阵分别做标准化(
scale()),使每个PC的均值为0、标准差为1
如果要完全复刻autoplot的效果,按以下步骤生成数据:
d <- iris m1 <- prcomp(d[,1:4], scale=T) # 处理样本得分:标准化(和autoplot默认一致) scaled_scores <- as.data.frame(scale(m1$x[,1:2])) # 处理载荷:先乘PC标准差,再标准化 loadings_step1 <- m1$rotation[,1:2] %*% diag(m1$sdev[1:2]) scaled_loadings <- as.data.frame(scale(loadings_step1)) scaled_loadings$variable <- rownames(m1$rotation)
如果不需要标准化,只想让载荷和原始得分同尺度,简化为:
# 原始得分(不标准化) scores <- as.data.frame(m1$x[,1:2]) # 载荷仅乘PC标准差 scaled_loadings <- as.data.frame(m1$rotation[,1:2] %*% diag(m1$sdev[1:2])) scaled_loadings$variable <- rownames(m1$rotation)
3. 用ggplot2自定义绘图
以原始尺度的得分和载荷为例,绘制带载荷向量和标签的PCA图:
library(ggplot2) ggplot() + # 绘制样本得分点 geom_point(data = scores, aes(x = PC1, y = PC2), alpha = 0.7) + # 绘制载荷向量(从原点出发) geom_segment(data = scaled_loadings, aes(x = 0, y = 0, xend = PC1, yend = PC2), arrow = arrow(length = unit(0.2, "cm")), color = "#E64B35", linewidth = 1) + # 添加变量标签(稍微偏移避免和箭头重叠) geom_text(data = scaled_loadings, aes(x = PC1 * 1.1, y = PC2 * 1.1, label = variable), color = "#E64B35", fontface = "bold") + # 标注主成分解释率 labs(x = paste0("PC1 (", round(m1$sdev[1]^2/sum(m1$sdev^2)*100, 1), "%)"), y = paste0("PC2 (", round(m1$sdev[2]^2/sum(m1$sdev^2)*100, 1), "%)")) + theme_minimal() + theme(panel.grid = element_blank())
关键说明
- 载荷向量的长度反映变量对主成分的贡献:向量越长,变量与该PC的相关性越强
- 乘PC标准差的目的是让载荷的尺度与得分对齐,这样在同一坐标系下,向量的相对长度更有意义
- 如果选择标准化得分和载荷,所有PC的方差会被统一为1,适合对比不同PCA模型的结果
内容的提问来源于stack exchange,提问作者Ryan Utz
相关产品推荐
相关产品推荐

