关于 R 中 princomp 和 prcomp 的 区别

主成分分析方法从统计学上讲对子特征提取,典型特征,相似性有重要的作用。简而言之,就是在导致结果的所有因素中发现哪些少数因素是概括了数据集整个特征空间中所包含的信息,因而称为主成分分析。常用的方法有 :

PCA (principle component analysis)

LDA(latent discriminative analysis)    <-- 偶看了一篇论文apple 2005年时候的语音合成技术就是基于此算法,在此提一下

SVD(single value decomposition)

不过在我看来,核心都是利用正交化的思想构造特征值矩阵。


R语言中,实现这个方法的函数 princomp , prcomp 等,这里来介绍这两种方法的不同 。读了开发人的邮件后,总结主要如下:

                                        

 princomp    prcomp       
R mode / Q mode只适用于R mode适用于R mode 和 Q mode
基于算法基于 协方差(covariance) 或者 相关矩阵(correlation) 提取的特征(eigen)   , 也叫 spectral decomposition基于SVD分解
载荷因子的R用法(不懂请把PCA基本算法搞懂)princomp.loadingsprcomp.rotation

  •   什么是R mode 和Q mode:
    • 首先,什么是 observation 和 variable:
      • observation 指 所有观察到的记录数,也就是数据集里面的行数,我们有时也会说有几条数据这个意思,而variable是指因素的个数。

               R mode  是指基于variable的分析 ,意思就是说在所有的observation里面,来研究variable之间的关系,哪些是主要的?是典型的?英文:similarity in the variables over subjects. 这里的R 我认为指normal,就是最平常的情况,数据数量大于变量(因素)数量,例如人口统计中,是人口多还是统计指标多?对吧。这里文档里面翻译成 observation 大于 variable。

                            Q mode  是指基于observation的分析,意思就是说在所有的variable里面,来研究observation之间的关系,哪两条记录相似? 英文:similarity in the subjects over variables。所以这里是指变量(因素)数量大于数据数量,与R 相对。

清楚了什么是R / Q mode  ,来看看 具体使用时候他们的异同点:

拿 iowa 一本书里的 protein.csv  数据举例,

1.  R mode / Q mode 实验

food = read.csv("protein.csv")
food[1,]
  Country RedMeat WhiteMeat Eggs Milk Fish Cereals Starch Nuts Fr.Veg
1 Albania    10.1       1.4  0.5  8.9  0.2    42.3    0.6  5.5    1.7

dim(food)
[1] 25 10

这里 数据大于变量,即行大于列,则应该是R mode的数据,来看prcomp 和 princomp得到的载荷(loadings)

pcafood <- prcomp(food[,-1], scale=TRUE)
str(pcafood$rotation)

num [1:9, 1:9] -0.303 -0.311 -0.427 -0.378 -0.136 ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:9] "RedMeat" "WhiteMeat" "Eggs" "Milk" ...
  ..$ : chr [1:9] "PC1" "PC2" "PC3" "PC4" ...

这里的载荷是一个9*9的矩阵
pcafood2 <- princomp(food[,-1], scale=TRUE)
str(pcafood2$loadings)

 loadings [1:9, 1:9] -0.1507 -0.1295 -0.0673 -0.4254 -0.127 ...
 - attr(*, "dimnames")=List of 2
  ..$ : chr [1:9] "RedMeat" "WhiteMeat" "Eggs" "Milk" ...
  ..$ : chr [1:9] "Comp.1" "Comp.2" "Comp.3" "Comp.4" ...

这里的载荷同样是9*9的矩阵
但是, 如果选用Q mode的数据(在那个网站下得到),再来看一下:
raw=read.csv("unempstates.csv")
raw[1,]
 AL  AK   AZ  AR  CA  CO  CT  DE FL  GA  HI  ID
1 6.4 7.1 10.5 7.3 9.3 5.8 9.4 7.7 10 8.3 9.9 5.5
   IL  IN  IA  KS  KY  LA  ME  MD   MA MI  MN MS  MO
1 6.4 6.9 4.2 4.3 5.7 6.2 8.8 6.9 11.1 10 6.2  7 5.8
   MT  NE  NV  NH   NJ  NM   NY  NC  ND  OH  OK   OR
1 5.8 3.6 9.8 7.2 10.5 8.9 10.2 6.7 3.2 8.3 6.4 10.1
   PA  RI  SC  SD  TN  TX  UT  VT  VA  WA  WV  WI
1 8.1 7.8 7.6 3.6 5.9 5.9 6.1 8.8 6.2 8.7 8.3 5.9
   WY
1 4.2

unempstates=t(raw)

dim(unempstates)

[1]  50 416
这里是一个反应美国** 的数据集,原数据集的行是美国50个州,列是各个指标,这里转置一下,变为Q mode的数据集unempstates
pcaunempstates <- prcomp(unempstates[,-1], scale=TRUE)
str(pcaunempstates$rotation)

num [1:415, 1:50] -0.031 -0.0315 -0.0316 -0.0321 -0.0328 ...
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:50] "PC1" "PC2" "PC3" "PC4" ...

pcaunempstates2 <- princomp(unempstates[,-1], scale=TRUE)

str(pcaunempstates2$loadings)


Error in princomp.default(unempstates[, -1], scale = TRUE) : 
  'princomp'只能在单位比变量多的情况下使用

这里可以看到,princomp不支持对Q mode 数据的pca处理,而prcomp 是可以的.

2. 载荷值的比较

实验前提一点,使用SVD分解和协方差方式做出来的结果其实应该是一样的或者接近的,因为这两种方法其实原理大致相同,只是一方需要有正定矩阵的约束条件

还是回到protein的例子,

food = read.csv("protein.csv")
pcafood <- prcomp(food[,-1],scale=TRUE)

               PC1         PC2         PC3
RedMeat   -0.3026094 -0.05625165 -0.29757957
WhiteMeat -0.3105562 -0.23685334  0.62389724
Eggs      -0.4266785 -0.03533576  0.18152828
Milk      -0.3777273 -0.18458877 -0.38565773
Fish      -0.1356499  0.64681970 -0.32127431
Cereals    0.4377434 -0.23348508  0.09591750
Starch    -0.2972477  0.35282564  0.24297503
Nuts       0.4203344  0.14331056 -0.05438778
Fr.Veg     0.1104199  0.53619004  0.40755612
                   PC4         PC5         PC6
RedMeat   -0.646476536  0.32216008 -0.45986989
WhiteMeat  0.036992271 -0.30016494 -0.12100707
Eggs      -0.313163873  0.07911048  0.36124872
Milk       0.003318279 -0.20041361  0.61843780
Fish       0.215955001 -0.29003065 -0.13679059
Cereals    0.006204117  0.23816783  0.08075842
Starch     0.336684733  0.73597332  0.14766670
Nuts      -0.330287545  0.15053689  0.44701001
Fr.Veg    -0.462055746 -0.23351666  0.11854972
                  PC7         PC8        PC9
RedMeat    0.15033385 -0.01985770  0.2459995
WhiteMeat -0.01966356 -0.02787648  0.5923966
Eggs      -0.44327151 -0.49120023 -0.3333861
Milk       0.46209500  0.08142193  0.1780841
Fish      -0.10639350 -0.44873197  0.3128262
Cereals    0.40496408 -0.70299504  0.1522596
Starch     0.15275311  0.11453956  0.1218582
Nuts      -0.40726235  0.18379989  0.5182749
Fr.Veg     0.44997782  0.09196337 -0.2029503


pcafood2 <- princomp(food[,-1],scale=TRUE)


Loadings:
          Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6
RedMeat   -0.151 -0.133         0.896 -0.289  0.229
WhiteMeat -0.129        -0.798 -0.185 -0.400       
Eggs                                               
Milk      -0.425 -0.831  0.220 -0.204 -0.117 -0.149
Fish      -0.127  0.292  0.522 -0.285 -0.559  0.256
Cereals    0.861 -0.406               -0.274  0.114
Starch                         -0.112 -0.241  0.327
Nuts       0.114         0.166  0.123        -0.565
Fr.Veg            0.169               -0.533 -0.645
          Comp.7 Comp.8 Comp.9
RedMeat                       
WhiteMeat -0.246 -0.261 -0.146
Eggs       0.142 -0.255  0.940
Milk                          
Fish      -0.336 -0.229       
Cereals                       
Starch     0.871 -0.155 -0.167
Nuts             -0.743 -0.232
Fr.Veg     0.180  0.482       



为什么这里两种方式算出来的载荷这么不一样? 后来分析得知,原因在于princomp的 cor参数,这个参数其实有两个选项,TRUE和FALSE,TRUE表示采用correlation方式计算,
FALSE 表示采用covariance方式计算。默认情况下,是采用FALSE值计算的。所以这里princomp计算的其实是covariance.而标准化(正态分布)后的covariance 其实
等价于correlation,并不再是 对应 covariance(X) 了。所以即使用covariance计算,也不可能产生和SVD 分解一样的结果,用式子表示,
就是  correlation = covariance( z-score(X) ) .

所以要使得两个结果一样,可以把 z-score的 normalization 给去掉,然后再试一次,这个时候应该是covariance(X)了:

pcafood2 <- princomp(food[,-1], cor=FALSE,scale=FALSE)

Loadings:
          Comp.1 Comp.2 Comp.3 Comp.4 Comp.5 Comp.6
RedMeat   -0.151 -0.133         0.896 -0.289  0.229
WhiteMeat -0.129        -0.798 -0.185 -0.400       
Eggs                                               
Milk      -0.425 -0.831  0.220 -0.204 -0.117 -0.149
Fish      -0.127  0.292  0.522 -0.285 -0.559  0.256
Cereals    0.861 -0.406               -0.274  0.114
Starch                         -0.112 -0.241  0.327
Nuts       0.114         0.166  0.123        -0.565
Fr.Veg            0.169               -0.533 -0.645
          Comp.7 Comp.8 Comp.9
RedMeat                       
WhiteMeat -0.246 -0.261 -0.146
Eggs       0.142 -0.255  0.940
Milk                          
Fish      -0.336 -0.229       
Cereals                       
Starch     0.871 -0.155 -0.167
Nuts             -0.743 -0.232
Fr.Veg     0.180  0.482  


pcafood <- prcomp(food[,-1],scale=FALSE)


                  PC1         PC2         PC3
RedMeat   -0.15065437 -0.13269468 -0.03183702
WhiteMeat -0.12948879 -0.04343486  0.79838375
Eggs      -0.06727094 -0.02094603  0.09809250
Milk      -0.42537632 -0.83085609 -0.21964423
Fish      -0.12697617  0.29230731 -0.52238799
Cereals    0.86086515 -0.40616852 -0.03819580
Starch    -0.06685119  0.07604862  0.03432274
Nuts       0.11390881  0.07006621 -0.16639124
Fr.Veg     0.02023530  0.16922131 -0.02217752
                  PC4         PC5           PC6
RedMeat   -0.89605088  0.28880267 -2.290658e-01
WhiteMeat  0.18534039  0.39975064  4.418893e-05
Eggs      -0.07583562  0.07877533  6.934069e-02
Milk       0.20364469  0.11700605  1.494390e-01
Fish       0.28510797  0.55887353 -2.561571e-01
Cereals    0.03449999  0.27438410 -1.138637e-01
Starch     0.11186694  0.24093950 -3.270186e-01
Nuts      -0.12290210 -0.08410214  5.645635e-01
Fr.Veg    -0.07364522  0.53305272  6.450846e-01
                  PC7         PC8         PC9
RedMeat    0.07965762 -0.06594051  0.09593232
WhiteMeat  0.24627505 -0.26052755  0.14578003
Eggs      -0.14159078 -0.25530955 -0.93990324
Milk      -0.03659099 -0.01145501  0.03906204
Fish       0.33586748 -0.22854504 -0.03552198
Cereals    0.01897181 -0.03504168 -0.03807529
Starch    -0.87124836 -0.15513110  0.16710135
Nuts      -0.08325422 -0.74349988  0.23193980
Fr.Veg    -0.18012371  0.48181384 -0.01306739



结果近似了,这里少许失真是因为svd是考虑平方根,所以算平方根的时候会有位数保留出现造成失真。


这是邮件

https://stat.ethz.ch/pipermail/r-help/2011-September/289101.html



  • 9
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值