R,有效方式,矩阵运算

时间:2013-03-04 09:52:31

标签: r matrix

我有一个大矩阵。目标是识别第1,2和3列中具有所有相等值的所有行,并计算每组行的第4列中的0的百分比。将所有这些百分比放在一个名为“data”的向量中。然后我需要三个向量(在每列上(最后一列除外)),它记录列的公共值。我们将这些向量称为:“factor1”,“factor2”和“factor3”,分别用于列1,2和3。 由于我的矩阵很大而且很多,我需要快速有效的计算。

例如我有这个矩阵:

    [,1][,2][,3][,4]
[1,]  1    1   1   0
[2,]  1    2   1   0
[3,]  3    2   1   0.6
[4,]  1    1   1   0.2
[5,]  1    2   1   0
[6,]  1    1   2   0.1
[7,]  3    2   1   0.9

这里我们将第1行和第4行组合在一起(基于第1,2和3列中的相等值)并计算0的百分比(在第4列中)(%0等于0.5)

然后我们将第2行和第5行分组并再次计算%0(等于1)

然后我们将行3和7分组并计算%0(等于0)

然后第6行是单独的,其%0(等于0)

以下是我想要的矢量:

> data = c(0.5,1,0,0)

> factor1 = c(1,1,3,1)

> factor2 = c(1,2,2,1)

> factor3 = c(1,1,1,2)

这些值的顺序并不重要。如果向量“data”中的值0.5在位置2中,那么所有因子的位置2应为1.

然后目标是运行以下aov:

> aov(data ~ factor1 * factor2 * factor3)

非常感谢你的帮助

3 个答案:

答案 0 :(得分:2)

重新创建矩阵:

df <- read.table(text="[,1] [,2] [,3] [,4]
[1,]  1    1   1   0
[2,]  1    2   1   0
[3,]  3    2   1   0.6
[4,]  1    1   1   0.2
[5,]  1    2   1   0
[6,]  1    1   2   0.1
[7,]  3    2   1   0.9",header=TRUE)
m <- as.matrix(df)
colnames(m) <- NULL

使用package data.table进行split-apply-combine。由于其效率,建议对大型数据集使用data.table。

library(data.table)
DT <- as.data.table(m)

DT.agg <- DT[,sum(V4==0)/length(V4),by=list(V1,V2,V3)]
setnames(DT.agg,c("factor1","factor2","factor3","data"))
print(DT.agg)
#   factor1 factor2 factor3 data
#1:       1       1       1  0.5
#2:       1       2       1  1.0
#3:       3       2       1  0.0
#4:       1       1       2  0.0

aov(data ~ factor1 * factor2 * factor3, data = DT.agg)

答案 1 :(得分:2)

如果您的矩阵非常大,请不要忘记在尝试时包含转换为data.table的成本。以下内容应该非常快。

colnames(m) <- c(paste0('factor', 1:3), 'data')
aggregate(data ~ ., data = m, function(x) mean(x!=0))

然而我测试了它,事实证明plyr实际上与data.table相当具有竞争力,并且聚合相当远(3x)。最新版本的plyr(1.8)已经比以前快得多。

在某些测试中,如果您首先转换为data.frame(即使您包含data.frame转换时间),我发现聚合变得更快(2x)。

所有发布的答案都没有真正缓慢。如果你有很多这些矩阵,我想它们都在文件中,如果你的代码很慢,我猜你可能会遇到瓶颈。有一些方法可以优化文件的矩阵读取(使用scan而不是read.table

(顺便说一下,你可能不应该对这些数据进行ANOVA)

答案 2 :(得分:0)

以下是plyr包的解决方案。如果m是您的矩阵:

m <- data.frame(m)
colnames(m) <- c("V1","V2","V3","data")
m2 <- ddply(m, .(V1,V2,V3), summarise, data=sum(data==0)/length(data))

给出了:

  V1 V2 V3 data
1  1  1  1  0.5
2  1  1  2  0.0
3  1  2  1  1.0
4  3  2  1  0.0

然后你可以这样做:

aov(data=m2, data ~ V1 * V2 * V3)

plyr并不总是最快的解决方案。