You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在ggplot中添加PCA载荷?生成载荷后添加遇报错

PCA载荷数据框添加到ggplot的问题解决

问题背景

我用以下代码生成了PCA载荷数据框:

PCAloadings <- data.frame(Variables = rownames(pca_res_t$rotation), pca_res_t$rotation)

但无法将其通过geom_segment添加到已有的PCA散点图中,尝试两种写法均报错,具体细节如下:

原有ggplot散点图代码

ggplot(data=sep_total_raw_data, aes(x=pc1t, y=pc2t))+
  geom_point(alpha=0.8, size=1,aes(colour=Data_Type, shape=Data_Type))+
  xlab("PC1 (53.83%)")+ ylab("PC2 (26.3%)")+ guides(colour=guide_legend(title="Data_Type"))+
  geom_mark_hull(concavity=5, expand=0, radius=0, aes(fill=Data_Type))+
  theme(panel.grid = element_blank(), panel.border = element_rect(fill = "transparent"))+
  geom_text(aes(label=Code, fontface="bold", colour=Data_Type))

尝试的代码及报错

尝试1

+ geom_segment(data = PCALoadings, aes(x=0,xend=xvar, y=0, yend=yvar), arrow = arrow(length = unit(0.025,"npc"),type = "open"),lwd=1)

报错:无法识别xvar和yvar

尝试2

+ geom_segment(data = PCALoadings, aes(x=0,xend=(pc1t*2), y=0, yend=(pc2t*2)), arrow = arrow(length = unit(1/2,"picas")), colour="black")

报错信息:

Error in `geom_segment()`:
! Problem while computing aesthetics.
ℹ Error occurred in the 4th layer.
Caused by error in `check_aesthetics()`:
! Aesthetics must be either length 1 or the same as the data (5)
✖ Fix the following mappings: `xend` and `yend`
Run `rlang::last_trace()` to see where the error occurred.

可复现代码(用iris数据集模拟)

ggplot(data=iris, aes(x=Petal.Length, y=Petal.Width))+
  geom_point(alpha=0.8, size=1,aes(colour=Species, shape=Species))+
  xlab("Petal Length")+ ylab("Petal Width")+ guides(colour=guide_legend(title="Species"))+
  geom_mark_hull(concavity=5, expand=0, radius=0, aes(fill=Species))+
  theme(panel.grid = element_blank(), panel.border = element_rect(fill = "transparent"))+geom_text(aes(label=Species, fontface="bold", colour=Species))

解决方案

核心问题分析

  1. 尝试1的问题:xvar和yvar不是PCAloadings数据框的实际列名,需替换为pca_res_t$rotation输出的真实列名(通常是PC1、PC2)。
  2. 尝试2的问题:pc1t是主数据集sep_total_raw_data的列,而geom_segment指定了data=PCALoadings,因此无法找到该列;同时载荷值通常较小,直接映射会导致箭头显示不明显,需先缩放匹配散点图坐标范围。

修正后的代码步骤

  1. 确认载荷数据框列名,对载荷进行缩放:
# 计算缩放因子,匹配散点图的坐标范围
scale_factor <- max(abs(sep_total_raw_data$pc1t), abs(sep_total_raw_data$pc2t)) / max(abs(PCAloadings$PC1), abs(PCAloadings$PC2)) * 0.8
PCAloadings$PC1_scaled <- PCAloadings$PC1 * scale_factor
PCAloadings$PC2_scaled <- PCAloadings$PC2 * scale_factor
  1. 在ggplot中添加载荷箭头:
ggplot(data=sep_total_raw_data, aes(x=pc1t, y=pc2t))+
  geom_point(alpha=0.8, size=1,aes(colour=Data_Type, shape=Data_Type))+
  xlab("PC1 (53.83%)")+ ylab("PC2 (26.3%)")+ guides(colour=guide_legend(title="Data_Type"))+
  geom_mark_hull(concavity=5, expand=0, radius=0, aes(fill=Data_Type))+
  theme(panel.grid = element_blank(), panel.border = element_rect(fill = "transparent"))+
  geom_text(aes(label=Code, fontface="bold", colour=Data_Type))+
  # 添加载荷箭头
  geom_segment(data = PCAloadings, aes(x=0, xend=PC1_scaled, y=0, yend=PC2_scaled),
               arrow = arrow(length = unit(0.025, "npc"), type = "open"), lwd=1, colour="black")+
  # 可选:添加载荷变量标签
  geom_text(data = PCAloadings, aes(x=PC1_scaled * 1.1, y=PC2_scaled * 1.1, label=Variables),
            colour="black", fontface="bold")

针对iris模拟数据的完整示例

# 对iris做PCA分析
iris_pca <- prcomp(iris[,1:4], scale.=TRUE)
# 生成载荷数据框
iris_loadings <- data.frame(Variables = rownames(iris_pca$rotation), iris_pca$rotation)
# 生成PCA得分数据
iris_scores <- as.data.frame(iris_pca$x)
iris_scores$Species <- iris$Species

# 缩放载荷
scale_factor <- max(abs(iris_scores$PC1), abs(iris_scores$PC2)) / max(abs(iris_loadings$PC1), abs(iris_loadings$PC2)) * 0.8
iris_loadings$PC1_scaled <- iris_loadings$PC1 * scale_factor
iris_loadings$PC2_scaled <- iris_loadings$PC2 * scale_factor

# 绘制带载荷箭头的PCA图
ggplot(data=iris_scores, aes(x=PC1, y=PC2))+
  geom_point(alpha=0.8, size=1,aes(colour=Species, shape=Species))+
  xlab(paste0("PC1 (", round(iris_pca$sdev[1]^2/sum(iris_pca$sdev^2)*100,2),"%)"))+ 
  ylab(paste0("PC2 (", round(iris_pca$sdev[2]^2/sum(iris_pca$sdev^2)*100,2),"%)"))+ 
  guides(colour=guide_legend(title="Species"))+
  geom_mark_hull(concavity=5, expand=0, radius=0, aes(fill=Species))+
  theme(panel.grid = element_blank(), panel.border = element_rect(fill = "transparent"))+
  geom_text(aes(label=Species, fontface="bold", colour=Species))+
  geom_segment(data = iris_loadings, aes(x=0, xend=PC1_scaled, y=0, yend=PC2_scaled),
               arrow = arrow(length = unit(0.025, "npc"), type = "open"), lwd=1, colour="black")+
  geom_text(data = iris_loadings, aes(x=PC1_scaled * 1.1, y=PC2_scaled * 1.1, label=Variables),
            colour="black", fontface="bold")

内容的提问来源于stack exchange,提问作者stakrawolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 16:57:53