用plyr计算组的样本协方差矩阵

时间:2010-04-28 07:13:10

标签: r

对于此示例,我将使用http://gettinggeneticsdone.blogspot.com/2009/11/split-apply-and-combine-in-r-using-plyr.html中的示例代码。所以,首先,让我们复制他们的示例数据:

mydata=data.frame(X1=rnorm(30), X2=rnorm(30,5,2),
SNP1=c(rep("AA",10), rep("Aa",10), rep("aa",10)),
SNP2=c(rep("BB",10), rep("Bb",10), rep("bb",10)))

我将在此示例中忽略SNP2,并假装SNP1中的值表示组成员身份。那么,我可能想要一些关于SNP1中每个组的摘要统计:“AA”,“Aa”,“aa”。

然后,如果我想计算每个变量的均值,那么使用它是有意义的(稍微修改它们的代码):

> ddply(mydata, c("SNP1"), function(df)
data.frame(meanX1=mean(df$X1), meanX2=mean(df$X2)))
  SNP1      meanX1   meanX2
1   aa  0.05178028 4.812302
2   Aa  0.30586206 4.820739
3   AA -0.26862500 4.856006

但是,如果我想要每个组的样本协方差矩阵怎么办?理想情况下,我想要一个3D数组,其中我有每个组的协方差矩阵,第三个维度表示相应的组。我尝试了以前代码的修改版本并获得了以下结果,这些结果使我确信我做错了。

> daply(mydata, c("SNP1"), function(df) cov(cbind(df$X1, df$X2)))
, ,  = 1


SNP1         1          2
  aa 1.4961210 -0.9496134
  Aa 0.8833190 -0.1640711
  AA 0.9942357 -0.9955837

, ,  = 2


SNP1          1        2
  aa -0.9496134 2.881515
  Aa -0.1640711 2.466105
  AA -0.9955837 4.938320

我认为第三维的dim()将是3,而是2.它实际上这是每个组的协方差矩阵的切片版本。如果我们手动计算aa的样本协方差矩阵,我们得到:

           [,1]       [,2]
[1,]  1.4961210 -0.9496134
[2,] -0.9496134  2.8815146

使用plyr,下面给出了我想要的list()形式:

> dlply(mydata, c("SNP1"), function(df) cov(cbind(df$X1, df$X2)))
$aa
           [,1]       [,2]
[1,]  1.4961210 -0.9496134
[2,] -0.9496134  2.8815146

$Aa
           [,1]       [,2]
[1,]  0.8833190 -0.1640711
[2,] -0.1640711  2.4661046

$AA
           [,1]       [,2]
[1,]  0.9942357 -0.9955837
[2,] -0.9955837  4.9383196

attr(,"split_type")
[1] "data.frame"
attr(,"split_labels")
  SNP1
1   aa
2   Aa
3   AA

但就像我之前说的那样,我真的很喜欢这个3D阵列。有关daply()或建议我出错的问题吗?当然,我可以将列表从dlply()转换为3D数组,但我不想这样做,因为我将在模拟中多次重复此过程。

作为旁注,我找到了一种方法(http://www.mail-archive.com/r-help@r-project.org/msg86328.html),它为每个组提供了样本协方差矩阵,但输出的对象是膨胀的。

提前致谢。

2 个答案:

答案 0 :(得分:4)

daply使分割变量成为数组中第一个维度。

a <- daply(mydata, c("SNP1"), function(df) cov(cbind(df$X1, df$X2)))
l <- dlply(mydata, c("SNP1"), function(df) cov(cbind(df$X1, df$X2)))

这样a[1, , ]l[[1]]对应相同的输出。正如wkmor1建议的那样,你可以使用aperm来重新排列尺寸,但我想更多地了解为什么初始形式不适合你的需要。

答案 1 :(得分:3)

怎么回事......

aperm(daply(mydata, c("SNP1"), function(df) cov(cbind(df$X1, df$X2))),perm=c(2,3,1))

'aperm'是数组,因为't'是矩阵。 perm参数指定了dim应该改变的方式。