1

我尝试使用数据集 USArressts 在 R 中使用princomp()principal()执行 PCA。但是,对于加载/旋转和分数,我得到了两个不同的结果。

首先,我将原始数据框居中并归一化,以便更容易比较输出。

library(psych)

trans_func <- function(x){
  x <- (x-mean(x))/sd(x)
  return(x)
}

A <- USArrests
USArrests <- apply(USArrests, 2, trans_func)

princompPCA <- princomp(USArrests, cor = TRUE)
principalPCA <- principal(USArrests, nfactors=4 , scores=TRUE, rotate = "none",scale=TRUE) 

然后我使用以下命令获得了加载和分数的结果:

princompPCA$loadings
principalPCA$loadings

你能帮我解释一下为什么会有区别吗?我们如何解释这些结果?

4

3 回答 3

3

在帮助文档的最后?principal

“特征向量由sqrt特征值重新缩放,以产生在因子分析中更典型的分量载荷。”

所以principal返回缩放的载荷。实际上,principal产生了一个通过主成分法估计的因子模型。

于 2016-10-02T17:49:40.367 回答
1

4年后,我想对这个问题提供更准确的答案。我以虹膜数据为例。

data = iris[, 1:4]

首先,通过特征分解做 PCA

eigen_res = eigen(cov(data))
l = eigen_res$values
q = eigen_res$vectors

那么最大特征值对应的特征向量就是因子载荷

q[,1]

我们可以将此作为参考或正确答案。现在我们通过不同的 r 函数检查结果。首先,通过函数'princomp'

res1 = princomp(data)
res1$loadings[,1]
# compare with 
q[,1]

没问题,这个函数实际上只是返回与 'eigen' 相同的结果。现在转到“校长”

library(psych)
res2 = principal(data, nfactors=4, rotate="none")
# the loadings of the first PC is
res2$loadings[,1]
# compare it with the results by eigendecomposition
sqrt(l[1])*q[,1] # re-scale the eigen vector by sqrt of eigen value

您可能会发现它们仍然不同。问题是'principal'函数默认对相关矩阵进行特征分解。注意:PCA 在重新调整变量时不是不变的。如果将代码修改为

res2 = principal(data, nfactors=4, rotate="none", cor="cov")
# the loadings of the first PC is
res2$loadings[,1]
# compare it with the results by eigendecomposition
sqrt(l[1])*q[,1] # re-scale the eigen vector by sqrt of eigen value

现在,您将得到与 'eigen' 和 'princomp' 相同的结果。

总结:

  1. 如果你想做PCA,你最好应用'princomp'函数。
  2. PCA 是因子模型的特例或因子模型的简化版本。它仅相当于特征分解。
  3. 我们可以应用 PCA 来获得因子模型的近似值。它不关心具体的因素,即因素模型中的epsilons。因此,如果您更改模型中的因子数量,您将获得相同的载荷估计。它不同于最大似然估计。
  4. 如果你在估计一个因子模型,你最好使用'principal'函数,因为它提供了更多的功能,比如旋转,通过不同的方法计算分数等等。
  5. 重新调整 PCA 模型的载荷不会对结果产生太大影响。由于您仍然将数据投影到相同的最佳方向,即最大化结果 PC 的变化。
于 2020-09-17T13:41:40.197 回答
0
ev <- eigen(R) # R is a correlation matrix of DATA
ev$vectors %*% diag(ev$values) %*% t(ev$vectors)

pc <- princomp(scale(DATA, center = F, scale = T),cor=TRUE) 
p <-principal(DATA, rotate="none")  

#eigen values
ev$values^0.5
pc$sdev
p$values^0.5

#eigen vectors - loadings
ev$vectors
pc$loadings
p$weights %*% diag(p$values^0.5)

pc$loading %*% diag(pc$sdev)
p$loadings 

#weights
ee <- diag(0,2)
for (j in 1:2) {
 for (i in 1:2) {
  ee[i,j] <- ev$vectors[i,j]/p$values[j]^0.5
 }
};ee 

#scores
s <- as.matrix(scale(DATA, center = T, scale = T)) %*% ev$vectors
scale(s)
p$scores
scale(pc$scores)
于 2020-09-17T17:41:27.187 回答