为什么 R 函数“princomp”和“prcomp”给出不同的特征值?

机器算法验证 r 主成分分析
2022-02-04 20:44:03

您可以使用十项全能数据集 {FactoMineR} 来重现这一点。问题是为什么计算的特征值不同于协方差矩阵的特征值。

以下是使用 的特征值princomp

> library(FactoMineR);data(decathlon)
> pr <- princomp(decathlon[1:10], cor=F)
> pr$sd^2
      Comp.1       Comp.2       Comp.3       Comp.4       Comp.5       Comp.6 
1.348073e+02 2.293556e+01 9.747263e+00 1.117215e+00 3.477705e-01 1.326819e-01 
      Comp.7       Comp.8       Comp.9      Comp.10 
6.208630e-02 4.938498e-02 2.504308e-02 4.908785e-03 

同样使用PCA

> res<-PCA(decathlon[1:10], scale.unit=FALSE, ncp=5, graph = FALSE)
> res$eig
          eigenvalue percentage of variance cumulative percentage of variance
comp 1  1.348073e+02           79.659589641                          79.65959
comp 2  2.293556e+01           13.552956464                          93.21255
comp 3  9.747263e+00            5.759799777                          98.97235
comp 4  1.117215e+00            0.660178830                          99.63252
comp 5  3.477705e-01            0.205502637                          99.83803
comp 6  1.326819e-01            0.078403653                          99.91643
comp 7  6.208630e-02            0.036687700                          99.95312
comp 8  4.938498e-02            0.029182305                          99.98230
comp 9  2.504308e-02            0.014798320                          99.99710
comp 10 4.908785e-03            0.002900673                         100.00000

你能解释一下为什么直接计算的特征值与那些不同吗?(特征向量相同):

> eigen(cov(decathlon[1:10]))$values
 [1] 1.381775e+02 2.350895e+01 9.990945e+00 1.145146e+00 3.564647e-01
 [6] 1.359989e-01 6.363846e-02 5.061961e-02 2.566916e-02 5.031505e-03

此外,替代prcomp方法给出与直接计算相同的特征值:

> prc <- prcomp(decathlon[1:10])
> prc$sd^2
 [1] 1.381775e+02 2.350895e+01 9.990945e+00 1.145146e+00 3.564647e-01
 [6] 1.359989e-01 6.363846e-02 5.061961e-02 2.566916e-02 5.031505e-03

为什么PCA/princompprcomp给出不同的特征值?

1个回答

正如评论中指出的那样,这是因为princomp使用作为除数,但是使用两者的直接计算而不是NprcompcovN1N

这在以下的“详细信息”部分中都有提及help(princomp)

请注意,默认计算使用除数“N”作为协方差矩阵。

详细信息部分help(prcomp)

与 不同princomp,方差是用通常的除数 N - 1 计算的。

您也可以在源代码中看到这一点。例如,princomp下面的源代码片段显示 ( ) 作为分母Nn.obscv

else if (is.null(covmat)) {
    dn <- dim(z)
    if (dn[1L] < dn[2L]) 
        stop("'princomp' can only be used with more units than variables")
    covmat <- cov.wt(z)
    n.obs <- covmat$n.obs
    cv <- covmat$cov * (1 - 1/n.obs)
    cen <- covmat$center
}

您可以通过指定covmat参数而不是参数来避免这种乘法x

princomp(covmat = cov(iris[,1:4]))$sd^2

有关 PCA 分数的更新:

您可以cor = TRUE在调用princomp中设置以对相关矩阵(而不是协方差矩阵)执行 PCA。这将导致princomp对数据进行评分,但仍将使用作为分母。zN

结果,princomp(scale(data))$scores并且princomp(data, cor = TRUE)$scores将因系数不同。(N1)/N