对于此示例,我将使用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),它为每个组提供了样本协方差矩阵,但输出的对象是膨胀的。
提前致谢。
答案 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应该改变的方式。