如何为ggplot双轴设置独立刻度:仅缩放载荷箭头不影响主数据
解决ggplot2绘制PCA Biplot时单独缩放载荷箭头的问题
核心思路
PCA得分(散点)和载荷(箭头)的尺度本身不一致,要实现仅缩放载荷箭头且不改变主轴刻度,需分离得分数据与载荷数据,手动对载荷进行缩放以匹配副轴范围,再分别绘制散点和箭头,最后添加自定义副轴。
具体实现代码
library(ggplot2) library(dplyr) # 1. 计算PCA并分离得分与载荷数据 iris_pca <- prcomp(iris[,1:4], scale. = TRUE) # 得分数据(主轴用原始数据,不做缩放) scores_df <- as.data.frame(iris_pca$x[,1:2]) %>% mutate(Species = iris$Species) # 载荷数据(需缩放匹配副轴limits=c(-0.8,0.8)) loadings_df <- as.data.frame(iris_pca$rotation[,1:2]) %>% mutate(Feature = rownames(.)) # 计算缩放因子:让载荷的最大绝对值匹配副轴上限0.8 scale_factor <- 0.8 / max(abs(loadings_df[,1:2])) loadings_scaled <- loadings_df %>% mutate(PC1 = PC1 * scale_factor, PC2 = PC2 * scale_factor) # 2. 绘制Biplot ggplot() + # 绘制得分散点(主轴保持原始PCA得分) geom_point(data = scores_df, aes(x = PC1, y = PC2, color = Species), size = 2) + # 绘制缩放后的载荷箭头 geom_segment(data = loadings_scaled, x = 0, y = 0, xend = PC1, yend = PC2, arrow = arrow(length = unit(0.2, "cm")), color = "darkred") + # 添加载荷标签 geom_text(data = loadings_scaled, aes(x = PC1 * 1.1, y = PC2 * 1.1, label = Feature), color = "darkred", fontface = "bold") + # 设置主轴刻度(保持原始得分范围) scale_x_continuous(name = "PC1", limits = range(scores_df$PC1)) + scale_y_continuous(name = "PC2", limits = range(scores_df$PC2), # 添加副轴,对应缩放后的载荷范围 sec.axis = sec_axis(~ . / scale_factor, name = "Loadings", limits = c(-0.8, 0.8))) + theme_minimal() + labs(title = "PCA Biplot of Iris Dataset")
关键说明
- 分离得分与载荷:避免ggplot自动统一尺度,手动控制两者的缩放逻辑
- 缩放载荷:通过计算
scale_factor将载荷的最大绝对值压缩到0.8,匹配副轴设定范围 - 副轴转换:
sec_axis(~ . / scale_factor)实现主轴得分到副轴载荷的反向转换,确保刻度对应关系正确 - 主轴保持不变:用原始得分数据的范围设置主轴
limits,完全不影响散点的显示位置与主轴刻度
内容的提问来源于stack exchange,提问作者Farhan
相关产品推荐
相关产品推荐

