关于 R 中 princomp 和 prcomp 的 区别

来源:互联网 发布:encore制谱软件 编辑:程序博客网 时间:2024/05/20 12:50

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

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.Veg1 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  ID1 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  MO1 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   OR1 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  WI1 8.1 7.8 7.6 3.6 5.9 5.9 6.1 8.8 6.2 8.7 8.3 5.9   WY1 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         PC3RedMeat   -0.3026094 -0.05625165 -0.29757957WhiteMeat -0.3105562 -0.23685334  0.62389724Eggs      -0.4266785 -0.03533576  0.18152828Milk      -0.3777273 -0.18458877 -0.38565773Fish      -0.1356499  0.64681970 -0.32127431Cereals    0.4377434 -0.23348508  0.09591750Starch    -0.2972477  0.35282564  0.24297503Nuts       0.4203344  0.14331056 -0.05438778Fr.Veg     0.1104199  0.53619004  0.40755612                   PC4         PC5         PC6RedMeat   -0.646476536  0.32216008 -0.45986989WhiteMeat  0.036992271 -0.30016494 -0.12100707Eggs      -0.313163873  0.07911048  0.36124872Milk       0.003318279 -0.20041361  0.61843780Fish       0.215955001 -0.29003065 -0.13679059Cereals    0.006204117  0.23816783  0.08075842Starch     0.336684733  0.73597332  0.14766670Nuts      -0.330287545  0.15053689  0.44701001Fr.Veg    -0.462055746 -0.23351666  0.11854972                  PC7         PC8        PC9RedMeat    0.15033385 -0.01985770  0.2459995WhiteMeat -0.01966356 -0.02787648  0.5923966Eggs      -0.44327151 -0.49120023 -0.3333861Milk       0.46209500  0.08142193  0.1780841Fish      -0.10639350 -0.44873197  0.3128262Cereals    0.40496408 -0.70299504  0.1522596Starch     0.15275311  0.11453956  0.1218582Nuts      -0.40726235  0.18379989  0.5182749Fr.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.6RedMeat   -0.151 -0.133         0.896 -0.289  0.229WhiteMeat -0.129        -0.798 -0.185 -0.400       Eggs                                               Milk      -0.425 -0.831  0.220 -0.204 -0.117 -0.149Fish      -0.127  0.292  0.522 -0.285 -0.559  0.256Cereals    0.861 -0.406               -0.274  0.114Starch                         -0.112 -0.241  0.327Nuts       0.114         0.166  0.123        -0.565Fr.Veg            0.169               -0.533 -0.645          Comp.7 Comp.8 Comp.9RedMeat                       WhiteMeat -0.246 -0.261 -0.146Eggs       0.142 -0.255  0.940Milk                          Fish      -0.336 -0.229       Cereals                       Starch     0.871 -0.155 -0.167Nuts             -0.743 -0.232Fr.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.6RedMeat   -0.151 -0.133         0.896 -0.289  0.229WhiteMeat -0.129        -0.798 -0.185 -0.400       Eggs                                               Milk      -0.425 -0.831  0.220 -0.204 -0.117 -0.149Fish      -0.127  0.292  0.522 -0.285 -0.559  0.256Cereals    0.861 -0.406               -0.274  0.114Starch                         -0.112 -0.241  0.327Nuts       0.114         0.166  0.123        -0.565Fr.Veg            0.169               -0.533 -0.645          Comp.7 Comp.8 Comp.9RedMeat                       WhiteMeat -0.246 -0.261 -0.146Eggs       0.142 -0.255  0.940Milk                          Fish      -0.336 -0.229       Cereals                       Starch     0.871 -0.155 -0.167Nuts             -0.743 -0.232Fr.Veg     0.180  0.482  


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


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



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


这是邮件

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



5 1
原创粉丝点击