我有一个大矩阵。目标是识别第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)
非常感谢你的帮助
答案 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
并不总是最快的解决方案。