You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

FactoMineR::PCA()与base::prcomp()结果不一致问题问询

为什么FactoMineR::PCA和base::prcomp的PCA结果不一致?

你遇到的这个差异其实是两个函数在PCA实现细节上的几个关键不同点导致的,我来逐一拆解:

1. 主成分的符号差异

主成分本身的方向是任意的——只要它能解释相同的方差,正负方向都是有效的。你看到的“数值相似但不完全相同”很可能是主成分的符号相反,比如prcomp的第一主成分是[1.2, -3.4, ...],而FactoMineR的是[-1.2, 3.4, ...],这属于正常现象,完全不影响PCA的解释效果。

2. 标准化(缩放)的计算细节不同

这是最容易导致数值差异的核心原因:

  • prcomp(scale. = TRUE) 使用样本标准差计算标准化,也就是除以 n-1(无偏估计);
  • FactoMineR::PCA(scale.unit = TRUE) 使用总体标准差计算标准化,也就是除以 n(有偏估计)。

你尝试用scale(df)后再传入FactoMineR的PCA,但scale()默认也是用样本标准差(除以n-1),这时候如果设置scale.unit = FALSE,理论上应该和prcomp的标准化结果一致,但可能因为后续计算路径的不同,还存在微小的浮点精度差异。

验证这一点可以手动计算:

# 手动计算两种标准差
sd_sample <- apply(df, 2, sd)  # 样本标准差(n-1)
sd_pop <- apply(df, 2, function(x) sqrt(mean((x-mean(x))^2)))  # 总体标准差(n)

# 对比两者的比值,n=64时应该接近sqrt(64/63)≈1.0079
head(sd_sample / sd_pop)

3. 主成分数量的差异

当样本数n小于特征数p时(比如NCI60的64个样本,6830个特征),PCA最多只能生成n-1个有意义的主成分(因为协方差矩阵的秩最多是n-1):

  • prcomp会自动返回所有n-1个主成分;
  • FactoMineR::PCAncp参数如果设置大于n-1,实际只会返回n-1个主成分,但你看到的“缺失一列”可能是因为浮点精度问题,某个方差接近0的主成分被函数自动过滤,或是两者对矩阵秩的判断略有不同。

4. 底层计算方法的差异

  • prcomp采用**奇异值分解(SVD)**来计算PCA,这种方法数值稳定性更好;
  • FactoMineR::PCA则是基于协方差矩阵的特征值分解,当特征数远大于样本数时,协方差矩阵的计算可能引入更多数值误差,导致结果和SVD方法有微小差异。

如何让两者结果一致?

如果你想让两个函数的结果尽可能对齐,可以这样做:

# 方法1:prcomp使用总体标准差标准化
df_scaled_pop <- scale(df, center = TRUE, scale = apply(df, 2, function(x) sqrt(mean((x-mean(x))^2))))
pca_prcomp_pop <- prcomp(df_scaled_pop, scale. = FALSE)

# 方法2:FactoMineR使用样本标准差标准化
df_scaled_sample <- scale(df)
pca_facto_sample <- FactoMineR::PCA(df_scaled_sample, scale.unit = FALSE, graph = FALSE, ncp = 63)

# 调整符号后对比,数值绝对值应该几乎一致
head(pca_prcomp_pop$x[,1] * -1)
head(pca_facto_sample$ind$coord[,1])

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

火山引擎 最新活动