stats
默认加载包,提供prcomp
与princomp
函数进行PCA计算psych
心理学研究包,提供principal
FactoMineR
多元分析包,提供PCA
函数进行PCA计算不同包中函数计算特征值并无差异,但由于对具体概念的理解不一致,导致同一参数的数值有一定区别,因此要对概念加以区分。
特征值指的是相关矩阵或者协方差矩阵的特征值。
特征值等于各主成分的方差,其相对比例可理解为方差解释度或贡献度。
特征值的平方根表示的是主成分得分的标准偏差(standard deviation),即prcomp
结果中的sdev
。
特征向量是主成分对于原始变量的线性转换系数矩阵(主成分得分系数)。
标准化后的原始变量与特征向量的矩阵积为主成分得分。
特征向量是单位向量(unit-length),其列平方和等于1。
从列上看,同一PC的特征向量的平方数等于FactoMineR
包中PCA
函数计算结果中的contribution
,理解为各变量对其主成分方差的贡献。等于。
一般定义为原始变量与主成分得分之间的相关系数,等于特征向量乘以特征值的平方根。
特征矩阵可以认为是单位标准化(unit-scaled,列平方和为1)的载荷。
从列上看,各变量对同一主成分的载荷的平方和等于其特征值(主成分的方差),理解为各变量对该主成分的贡献。
从行上看,同一变量对各主成分的载荷的平方(FactoMineR
包中PCA
函数计算结果中的cos2
),理解为各主成分对该变量方差的解释度,其和值为1(变量的方差)。
线性转换系数矩阵,经常与特征向量矩阵
混淆。因子得分系数数值上等于特征向量
除以特征值的平方根,因此相当于标准化的特征向量。
得分可分为主成分得分与因子得分,因子得分数值上等于主成分得分除以特征值的平方根,相当于标准化的主成分得分。
主成分得分为原始向量经过特征矩阵线性转换后的投影值。主成分得分矩阵的协方差为对角矩阵,且对角元素为特征值,非对角元素接近0。
因子得分为原始向量经因子得分系数权重(weight)转换后的投影值。因子得分矩阵的协方差为对角矩阵,对角元素为1,非对角元素接近0。
# 手动推导 --------------------------------------------------------------------
dt=scale(iris[,1:4]) #z-score标准化
head(dt)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## [1,] -0.8976739 1.01560199 -1.335752 -1.311052
## [2,] -1.1392005 -0.13153881 -1.335752 -1.311052
## [3,] -1.3807271 0.32731751 -1.392399 -1.311052
## [4,] -1.5014904 0.09788935 -1.279104 -1.311052
## [5,] -1.0184372 1.24503015 -1.335752 -1.311052
## [6,] -0.5353840 1.93331463 -1.165809 -1.048667
rm1=cor(dt) # 相关矩阵
rm1
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## Sepal.Length 1.0000000 -0.1175698 0.8717538 0.8179411
## Sepal.Width -0.1175698 1.0000000 -0.4284401 -0.3661259
## Petal.Length 0.8717538 -0.4284401 1.0000000 0.9628654
## Petal.Width 0.8179411 -0.3661259 0.9628654 1.0000000
rs1=eigen(rm1) # 特征值分解
rs1
## eigen() decomposition
## $values
## [1] 2.91849782 0.91403047 0.14675688 0.02071484
##
## $vectors
## [,1] [,2] [,3] [,4]
## [1,] 0.5210659 -0.37741762 0.7195664 0.2612863
## [2,] -0.2693474 -0.92329566 -0.2443818 -0.1235096
## [3,] 0.5804131 -0.02449161 -0.1421264 -0.8014492
## [4,] 0.5648565 -0.06694199 -0.6342727 0.5235971
val=rs1$value # 特征值,即各PC的方差
val
## [1] 2.91849782 0.91403047 0.14675688 0.02071484
val_sd=sqrt(val) # 各PC的方差标准差
val_sd
## [1] 1.7083611 0.9560494 0.3830886 0.1439265
val/sum(val) # 各PC的方差解释度
## [1] 0.729624454 0.228507618 0.036689219 0.005178709
val/sum(val)|>cumsum() # 累计解释度
## [1] 0.729624454 0.228507618 0.036689219 0.005178709
U=rs1$vectors # 特征向量
apply(U^2,2,sum) # 各PC单位特征向量,列平方和(模)为1
## [1] 1 1 1 1
PC=dt %*% U # 得分矩阵
colnames(PC) <- c("PC1","PC2","PC3","PC4")
head(PC)
## PC1 PC2 PC3 PC4
## [1,] -2.257141 -0.4784238 0.12727962 0.024087508
## [2,] -2.074013 0.6718827 0.23382552 0.102662845
## [3,] -2.356335 0.3407664 -0.04405390 0.028282305
## [4,] -2.291707 0.5953999 -0.09098530 -0.065735340
## [5,] -2.381863 -0.6446757 -0.01568565 -0.035802870
## [6,] -2.068701 -1.4842053 -0.02687825 0.006586116
cov(PC) # 得分矩阵协方差为对角矩阵,且对角元素为特征值,非对角元素接近0。
## PC1 PC2 PC3 PC4
## PC1 2.918498e+00 1.002833e-15 5.273639e-16 2.443472e-16
## PC2 1.002833e-15 9.140305e-01 1.249926e-16 8.745985e-18
## PC3 5.273639e-16 1.249926e-16 1.467569e-01 -9.267896e-17
## PC4 2.443472e-16 8.745985e-18 -9.267896e-17 2.071484e-02
apply(PC,2,var) # 主成分得分的方差等于特征值
## PC1 PC2 PC3 PC4
## 2.91849782 0.91403047 0.14675688 0.02071484
loadings= U %*% diag(sqrt(val)) # 载荷loading=特征向量*sqrt(val)
loadings
## [,1] [,2] [,3] [,4]
## [1,] 0.8901688 -0.36082989 0.27565767 0.03760602
## [2,] -0.4601427 -0.88271627 -0.09361987 -0.01777631
## [3,] 0.9915552 -0.02341519 -0.05444699 -0.11534978
## [4,] 0.9649790 -0.06399985 -0.24298265 0.07535950
cor(dt,PC) # 载荷数值上等于各变量与PC的相关系数
## PC1 PC2 PC3 PC4
## Sepal.Length 0.8901688 -0.36082989 0.27565767 0.03760602
## Sepal.Width -0.4601427 -0.88271627 -0.09361987 -0.01777631
## Petal.Length 0.9915552 -0.02341519 -0.05444699 -0.11534978
## Petal.Width 0.9649790 -0.06399985 -0.24298265 0.07535950
loadings %*% t(loadings) # 再现相关矩阵cor(dt)
## [,1] [,2] [,3] [,4]
## [1,] 1.0000000 -0.1175698 0.8717538 0.8179411
## [2,] -0.1175698 1.0000000 -0.4284401 -0.3661259
## [3,] 0.8717538 -0.4284401 1.0000000 0.9628654
## [4,] 0.8179411 -0.3661259 0.9628654 1.0000000
loadings^2
## [,1] [,2] [,3] [,4]
## [1,] 0.7924004 0.130198208 0.075987149 0.0014142127
## [2,] 0.2117313 0.779188012 0.008764681 0.0003159971
## [3,] 0.9831817 0.000548271 0.002964475 0.0133055723
## [4,] 0.9311844 0.004095980 0.059040571 0.0056790544
loadings^2|>colSums() # 载荷平方的列和=特征值
## [1] 2.91849782 0.91403047 0.14675688 0.02071484
loadings^2|>rowSums() # 载荷平方的行和=1,理解为各PC对变量的解释度
## [1] 1 1 1 1
princomp
函数princomp
’` 使用特征值分解方法,只能在记录数比变量多的情况下使用,一般不推荐。
在princomp
输出中,loading
为特征向量矩阵,需要格外注意!!!
pca1=princomp(iris[,1:4],cor=T,scores=T)
summary(pca1)
## Importance of components:
## Comp.1 Comp.2 Comp.3 Comp.4
## Standard deviation 1.7083611 0.9560494 0.38308860 0.143926497
## Proportion of Variance 0.7296245 0.2285076 0.03668922 0.005178709
## Cumulative Proportion 0.7296245 0.9581321 0.99482129 1.000000000
pca1$sdev # 主成分标准偏差
## Comp.1 Comp.2 Comp.3 Comp.4
## 1.7083611 0.9560494 0.3830886 0.1439265
pca1$sdev^2 # 特征值
## Comp.1 Comp.2 Comp.3 Comp.4
## 2.91849782 0.91403047 0.14675688 0.02071484
pca1$loadings # 特征向量
##
## Loadings:
## Comp.1 Comp.2 Comp.3 Comp.4
## Sepal.Length 0.521 0.377 0.720 0.261
## Sepal.Width -0.269 0.923 -0.244 -0.124
## Petal.Length 0.580 -0.142 -0.801
## Petal.Width 0.565 -0.634 0.524
##
## Comp.1 Comp.2 Comp.3 Comp.4
## SS loadings 1.00 1.00 1.00 1.00
## Proportion Var 0.25 0.25 0.25 0.25
## Cumulative Var 0.25 0.50 0.75 1.00
head(pca1$scores) # PC得分矩阵
## Comp.1 Comp.2 Comp.3 Comp.4
## [1,] -2.264703 0.4800266 0.12770602 0.02416820
## [2,] -2.080961 -0.6741336 0.23460885 0.10300677
## [3,] -2.364229 -0.3419080 -0.04420148 0.02837705
## [4,] -2.299384 -0.5973945 -0.09129011 -0.06595556
## [5,] -2.389842 0.6468354 -0.01573820 -0.03592281
## [6,] -2.075631 1.4891775 -0.02696829 0.00660818
prcomp
函数prcomp
使用奇异值分解(SVD)方法,一般推荐。
prcomp
的输出结果中用rotation
表示特征向量矩阵;用x
表示PC得分矩阵。
pca2=prcomp(iris[,1:4],scale. = T)
pca2 |> summary()
## Importance of components:
## PC1 PC2 PC3 PC4
## Standard deviation 1.7084 0.9560 0.38309 0.14393
## Proportion of Variance 0.7296 0.2285 0.03669 0.00518
## Cumulative Proportion 0.7296 0.9581 0.99482 1.00000
pca2$sdev # 主成分标准偏差
## [1] 1.7083611 0.9560494 0.3830886 0.1439265
pca2$sdev^2
## [1] 2.91849782 0.91403047 0.14675688 0.02071484
pca2$rotation #特征向量
## PC1 PC2 PC3 PC4
## Sepal.Length 0.5210659 -0.37741762 0.7195664 0.2612863
## Sepal.Width -0.2693474 -0.92329566 -0.2443818 -0.1235096
## Petal.Length 0.5804131 -0.02449161 -0.1421264 -0.8014492
## Petal.Width 0.5648565 -0.06694199 -0.6342727 0.5235971
head(pca2$x) # 得分矩阵
## PC1 PC2 PC3 PC4
## [1,] -2.257141 -0.4784238 0.12727962 0.024087508
## [2,] -2.074013 0.6718827 0.23382552 0.102662845
## [3,] -2.356335 0.3407664 -0.04405390 0.028282305
## [4,] -2.291707 0.5953999 -0.09098530 -0.065735340
## [5,] -2.381863 -0.6446757 -0.01568565 -0.035802870
## [6,] -2.068701 -1.4842053 -0.02687825 0.006586116
psych::principal
函数在psych::principal
输出中:
## determine the number of PCs
#fp=fa.parallel(dt,fa="pc",n.iter=100)
# extract PCs
pca3=psych::principal(dt,nfactors = 4,rotate="none")
#principal(dt,nfactors = 2,rotate="varimax",score=T)
pca3$values # 特征值
## [1] 2.91849782 0.91403047 0.14675688 0.02071484
pca3$loadings # 因子载荷,即特征向量*sqrt(特征值)
##
## Loadings:
## PC1 PC2 PC3 PC4
## Sepal.Length 0.890 0.361 -0.276
## Sepal.Width -0.460 0.883
## Petal.Length 0.992 0.115
## Petal.Width 0.965 0.243
##
## PC1 PC2 PC3 PC4
## SS loadings 2.918 0.914 0.147 0.021
## Proportion Var 0.730 0.229 0.037 0.005
## Cumulative Var 0.730 0.958 0.995 1.000
pca3$weights # 因子得分系数,即特征向量/sqrt(特征值)
## PC1 PC2 PC3 PC4
## Sepal.Length 0.3050092 0.39476790 -1.8783288 -1.8154147
## Sepal.Width -0.1576642 0.96574053 0.6379250 0.8581437
## Petal.Length 0.3397485 0.02561751 0.3710013 5.5684621
## Petal.Width 0.3306423 0.07001938 1.6556816 -3.6379482
head(pca3$scores) # 因子得分=原始数据 %*% 因子得分系数矩
## PC1 PC2 PC3 PC4
## [1,] -1.321232 0.5004175 -0.33224592 -0.16735979
## [2,] -1.214037 -0.7027698 -0.61036929 -0.71330052
## [3,] -1.379296 -0.3564318 0.11499664 -0.19650520
## [4,] -1.341465 -0.6227710 0.23750458 0.45672855
## [5,] -1.394238 0.6743121 0.04094522 0.24875802
## [6,] -1.210927 1.5524358 0.07016197 -0.04576028
dt %*% pca3$weights |> head() # 因子得分
## PC1 PC2 PC3 PC4
## [1,] -1.321232 0.5004175 -0.33224592 -0.16735979
## [2,] -1.214037 -0.7027698 -0.61036929 -0.71330052
## [3,] -1.379296 -0.3564318 0.11499664 -0.19650520
## [4,] -1.341465 -0.6227710 0.23750458 0.45672855
## [5,] -1.394238 0.6743121 0.04094522 0.24875802
## [6,] -1.210927 1.5524358 0.07016197 -0.04576028
cov(pca3$scores) # 对角元素为1,而PC得分的协方差为特征值
## PC1 PC2 PC3 PC4
## PC1 1.000000e+00 2.195696e-16 -2.320877e-16 1.311770e-15
## PC2 2.195696e-16 1.000000e+00 7.315978e-16 -3.200948e-16
## PC3 -2.320877e-16 7.315978e-16 1.000000e+00 3.156702e-17
## PC4 1.311770e-15 -3.200948e-16 3.156702e-17 1.000000e+00
apply(pca3$scores,2,var) # 方差为1,而PC得分的方差为特征值
## PC1 PC2 PC3 PC4
## 1 1 1 1
# 可见因子得分是经特征值标准化后的主成分得分。
FactoMineR::PCA
函数在FactoMineR::PCA
中输出的结果也与psych
中较为一致,且输出的图为相关图。
需要注意的是FactoMineR::PCA
包作者认为loading
就是转换矩阵(特征向量,与princomp、prcomp函数中的loading是一个意思),但是他也认为更值得关注的是相关性
(cor),即我们之前提到的loading
。
除特征值外,PCA
函数分var
(变量)与ind
(样本)两部分输出。其中均包含:
var
中为变量与PC的相关系数;ind
中为PC得分。coord
数值平方占行和的比例,表示PC对var
或ind
的代表性coord
数值平方占列和的比例,表示var
或ind
对PC的贡献pacman::p_load(FactoMineR)
res.pca <- PCA(dt,graph=F)
#summary(res.pca)
plot(res.pca,choix="var")
dimdesc(res.pca, axes = 1:2)
## $Dim.1
##
## Link between the variable and the continuous variables (R-square)
## =================================================================================
## correlation p.value
## Petal.Length 0.9915552 3.369916e-133
## Petal.Width 0.9649790 6.609632e-88
## Sepal.Length 0.8901688 2.190813e-52
## Sepal.Width -0.4601427 3.139724e-09
##
## $Dim.2
##
## Link between the variable and the continuous variables (R-square)
## =================================================================================
## correlation p.value
## Sepal.Width 0.8827163 2.123801e-50
## Sepal.Length 0.3608299 5.731933e-06
#特征根
res.pca$eig
## eigenvalue percentage of variance cumulative percentage of variance
## comp 1 2.91849782 72.9624454 72.96245
## comp 2 0.91403047 22.8507618 95.81321
## comp 3 0.14675688 3.6689219 99.48213
## comp 4 0.02071484 0.5178709 100.00000
res.pca$eig|>sqrt()
## eigenvalue percentage of variance cumulative percentage of variance
## comp 1 1.7083611 8.5418057 8.541806
## comp 2 0.9560494 4.7802470 9.788422
## comp 3 0.3830886 1.9154430 9.974073
## comp 4 0.1439265 0.7196325 10.000000
#变量分析
# res.pca$var
# 相关图中的坐标
res.pca$var$coord
## Dim.1 Dim.2 Dim.3 Dim.4
## Sepal.Length 0.8901688 0.36082989 -0.27565767 -0.03760602
## Sepal.Width -0.4601427 0.88271627 0.09361987 0.01777631
## Petal.Length 0.9915552 0.02341519 0.05444699 0.11534978
## Petal.Width 0.9649790 0.06399985 0.24298265 -0.07535950
# prcomp中的loading*sqrt(eigenvalue)
mapply(`*`,as.data.frame(pca2$rotation),pca2$sdev)
## PC1 PC2 PC3 PC4
## [1,] 0.8901688 -0.36082989 0.27565767 0.03760602
## [2,] -0.4601427 -0.88271627 -0.09361987 -0.01777631
## [3,] 0.9915552 -0.02341519 -0.05444699 -0.11534978
## [4,] 0.9649790 -0.06399985 -0.24298265 0.07535950
# 变量与主成分得分的相关系数,数值与coord相同
res.pca$var$cor
## Dim.1 Dim.2 Dim.3 Dim.4
## Sepal.Length 0.8901688 0.36082989 -0.27565767 -0.03760602
## Sepal.Width -0.4601427 0.88271627 0.09361987 0.01777631
## Petal.Length 0.9915552 0.02341519 0.05444699 0.11534978
## Petal.Width 0.9649790 0.06399985 0.24298265 -0.07535950
#各主成分对特定变量的解释度(代表性)
res.pca$var$cos2
## Dim.1 Dim.2 Dim.3 Dim.4
## Sepal.Length 0.7924004 0.130198208 0.075987149 0.0014142127
## Sepal.Width 0.2117313 0.779188012 0.008764681 0.0003159971
## Petal.Length 0.9831817 0.000548271 0.002964475 0.0133055723
## Petal.Width 0.9311844 0.004095980 0.059040571 0.0056790544
#数值上等于cor的平方
res.pca$var$cor^2
## Dim.1 Dim.2 Dim.3 Dim.4
## Sepal.Length 0.7924004 0.130198208 0.075987149 0.0014142127
## Sepal.Width 0.2117313 0.779188012 0.008764681 0.0003159971
## Petal.Length 0.9831817 0.000548271 0.002964475 0.0133055723
## Petal.Width 0.9311844 0.004095980 0.059040571 0.0056790544
#cos2行和=1
res.pca$var$cos2 |> rowSums() # loading的行和
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 1 1 1
#每个变量对某一主成分的贡献
res.pca$var$contrib
## Dim.1 Dim.2 Dim.3 Dim.4
## Sepal.Length 27.150969 14.24440565 51.777574 6.827052
## Sepal.Width 7.254804 85.24748749 5.972245 1.525463
## Petal.Length 33.687936 0.05998389 2.019990 64.232089
## Petal.Width 31.906291 0.44812296 40.230191 27.415396
# 此处contrib数值=原始转换矩阵的平方数
pca2$rotation^2*100
## PC1 PC2 PC3 PC4
## Sepal.Length 27.150969 14.24440565 51.777574 6.827052
## Sepal.Width 7.254804 85.24748749 5.972245 1.525463
## Petal.Length 33.687936 0.05998389 2.019990 64.232089
## Petal.Width 31.906291 0.44812296 40.230191 27.415396
# 数值上等于cor平方占特征值的比例
mapply(`/`, as.data.frame(res.pca$var$cor^2),res.pca$eig[,1])*100
## Dim.1 Dim.2 Dim.3 Dim.4
## [1,] 27.150969 14.24440565 51.777574 6.827052
## [2,] 7.254804 85.24748749 5.972245 1.525463
## [3,] 33.687936 0.05998389 2.019990 64.232089
## [4,] 31.906291 0.44812296 40.230191 27.415396
#列之和=100
apply(res.pca$var$contrib,2,sum)
## Dim.1 Dim.2 Dim.3 Dim.4
## 100 100 100 100
#样本分析
#res.pca$ind
plot(res.pca,choix="ind")
head(res.pca$ind$coord) # 主成分得分
## Dim.1 Dim.2 Dim.3 Dim.4
## 1 -2.264703 0.4800266 -0.12770602 -0.02416820
## 2 -2.080961 -0.6741336 -0.23460885 -0.10300677
## 3 -2.364229 -0.3419080 0.04420148 -0.02837705
## 4 -2.299384 -0.5973945 0.09129011 0.06595556
## 5 -2.389842 0.6468354 0.01573820 0.03592281
## 6 -2.075631 1.4891775 0.02696829 -0.00660818
pca2$x|>head()
## PC1 PC2 PC3 PC4
## [1,] -2.257141 -0.4784238 0.12727962 0.024087508
## [2,] -2.074013 0.6718827 0.23382552 0.102662845
## [3,] -2.356335 0.3407664 -0.04405390 0.028282305
## [4,] -2.291707 0.5953999 -0.09098530 -0.065735340
## [5,] -2.381863 -0.6446757 -0.01568565 -0.035802870
## [6,] -2.068701 -1.4842053 -0.02687825 0.006586116
#某一主成分对样本的代表性,
res.pca$ind$cos2 |> head()
## Dim.1 Dim.2 Dim.3 Dim.4
## 1 0.9539975 0.04286032 0.0030335249 1.086460e-04
## 2 0.8927725 0.09369248 0.0113475382 2.187482e-03
## 3 0.9790410 0.02047578 0.0003422122 1.410446e-04
## 4 0.9346682 0.06308947 0.0014732682 7.690193e-04
## 5 0.9315095 0.06823959 0.0000403979 2.104697e-04
## 6 0.6600989 0.33978301 0.0001114335 6.690714e-06
#行上看,cos2数值表示的是样本得分平方数在所有主成分上之和的比例
((res.pca$ind$coord^2)/rowSums(res.pca$ind$coord^2) ) |> head()
## Dim.1 Dim.2 Dim.3 Dim.4
## 1 0.9539975 0.04286032 0.0030335249 1.086460e-04
## 2 0.8927725 0.09369248 0.0113475382 2.187482e-03
## 3 0.9790410 0.02047578 0.0003422122 1.410446e-04
## 4 0.9346682 0.06308947 0.0014732682 7.690193e-04
## 5 0.9315095 0.06823959 0.0000403979 2.104697e-04
## 6 0.6600989 0.33978301 0.0001114335 6.690714e-06
#对某个记录而言,所有成分(行)的cos2之和=1
apply(res.pca$ind$cos2,1,sum)|>head()
## 1 2 3 4 5 6
## 1 1 1 1 1 1
# contrib表示的样本占主成分得分的比例
res.pca$ind$contrib |> head()
## Dim.1 Dim.2 Dim.3 Dim.4
## 1 1.1715796 0.16806554 0.074085470 0.018798188
## 2 0.9891845 0.33146674 0.250034006 0.341474919
## 3 1.2768164 0.08526419 0.008875320 0.025915633
## 4 1.2077372 0.26029781 0.037858004 0.140000650
## 5 1.3046313 0.30516562 0.001125175 0.041530572
## 6 0.9841236 1.61748779 0.003303827 0.001405371
# 列上看,数值上contribtion为每个PC上,得分平方占列和的比例
mapply(`/`,as.data.frame(res.pca$ind$coord^2)*100,colSums(res.pca$ind$coord^2)) |> head()
## Dim.1 Dim.2 Dim.3 Dim.4
## [1,] 1.1715796 0.16806554 0.074085470 0.018798188
## [2,] 0.9891845 0.33146674 0.250034006 0.341474919
## [3,] 1.2768164 0.08526419 0.008875320 0.025915633
## [4,] 1.2077372 0.26029781 0.037858004 0.140000650
## [5,] 1.3046313 0.30516562 0.001125175 0.041530572
## [6,] 0.9841236 1.61748779 0.003303827 0.001405371
#对某个PC而言,所有变量(列)的贡献之和=100
apply(res.pca$ind$contrib,2,sum)
## Dim.1 Dim.2 Dim.3 Dim.4
## 100 100 100 100
res.pca$ind$dist |> head() # 样本点到原点的距离
## 1 2 3 4 5 6
## 2.318663 2.202387 2.389401 2.378389 2.476142 2.554734