1

我有一个大矩阵。目标是识别在第 1,2 和 3 列中具有所有相等值的所有行,并计算每组行在第 4 列中 0 的百分比。将所有这些百分比放入一个称为“数据”的向量中。然后我需要三个向量(每列(最后一列除外))来记录列的公共值。我们将这些向量分别称为:“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 列中)(%zero 等于 0.5)

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

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

然后第 6 行是单独的,它的 %zero (等于 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)

非常感谢你的帮助

4

3 回答 3

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

使用包 data.table 进行拆分-应用-组合。建议将 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)
于 2013-03-04T10:04:36.877 回答
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 转换时间),聚合会变得更快(2 倍)。

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

(顺便说一句,您可能不应该对这些数据进行方差分析)

于 2013-03-04T12:24:15.590 回答
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但是,并不总是最快的解决方案。

于 2013-03-04T10:10:02.493 回答