R:有没有一种简单的方法可以让ave()对矩阵起作用?
很抱歉,如果这看起来很琐碎,但在互联网上搜索了一段时间后,我找不到解决方案 我有一个矩阵和一个与列关联的因子向量。目标是分别获得所有因素的平均值,并保持原始矩阵结构。所以它可能类似于ave(),但在二维数组上工作 下面是一个粗略的演示:R:有没有一种简单的方法可以让ave()对矩阵起作用?,r,matrix,tapply,R,Matrix,Tapply,很抱歉,如果这看起来很琐碎,但在互联网上搜索了一段时间后,我找不到解决方案 我有一个矩阵和一个与列关联的因子向量。目标是分别获得所有因素的平均值,并保持原始矩阵结构。所以它可能类似于ave(),但在二维数组上工作 下面是一个粗略的演示: (mat <- rbind(1:5,6:10,11:15)) [,1] [,2] [,3] [,4] [,5] [1,] 1 2 3 4 5 [2,] 6 7 8 9 10 [3,]
(mat <- rbind(1:5,6:10,11:15))
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 6 7 8 9 10
[3,] 11 12 13 14 15
groups <- c(1,1,1,2,2)
mat[,groups==1] <- rowMeans(mat[,groups==1]) # I am asking about this part
mat[,groups==2] <- rowMeans(mat[,groups==2]) # ...
mat
[,1] [,2] [,3] [,4] [,5]
[1,] 2 2 2 4.5 4.5
[2,] 7 7 7 9.5 9.5
[3,] 12 12 12 14.5 14.5
(mat1)假设您希望用该行的平均值替换每行的每个元素,请尝试此操作,其中m
是您的矩阵:
ave(m, row(m))
如果这不是你想要的,请提供一个完整的例子,包括输入和输出
2)对于更新的问题,请尝试以下方法:
t(ave(t(m), group, t(row(m))))
或此等效变化:
ave(m, matrix(group, nrow(m), ncol(m), byrow = TRUE), row(m))
也许是这样:
mat.list <- Map(matrix, split(mat, groups[col(mat)]), nrow = nrow(mat))
mean.list <- Map(rowMeans, mat.list)
do.call(cbind, mean.list[groups])
mat.list如果有一个优化的函数,比如rowGroupMeans,那就太好了,但我不知道有这样的事情
我的解决方案是使用rowsum,如下所示:
means <- rowsum(t(mat), groups)/tabulate(groups)
t(means)[, groups]
1 1 1 2 2
[1,] 2 2 2 4.5 4.5
[2,] 7 7 7 9.5 9.5
[3,] 12 12 12 14.5 14.5
意味着我觉得第二个例子很接近。但它不能在我手中重现想要的结果。i、 e.我得到mat[2,]:(6.07.57.59.010.0)。应该是(79.59.5)有趣的方法。今天从你那里学到了一些东西。(不知道行()或列())。但是这有一个速度问题。这就像rowMeans(mat)和apply(mat,1,means)一样。rowMeans的速度要快得多,当矩阵行数达到数百万时,它就开始起作用了(请注意原始问题)。在大多数情况下,可读性比速度更重要。我很高兴接受你的答案。这是正确的,给了我一些新的想法。不过我觉得在这种情况下for循环更容易理解:)我真的认为我缺少了一些基本的单字函数。谢谢你的回复。您的解决方案对于rowMeans来说是最优雅、最快速的。然而,我以“rowMeans”为例(可能还不清楚),目标是实现完整的ave()类型方法。也就是说,我希望最终能够指定其他类型的函数(如rowMedians)。也许我会自己写一些包装。这里所有的答案都给了我一些想法。再次感谢你。
means <- rowsum(t(mat), groups)/tabulate(groups)
t(means)[, groups]
1 1 1 2 2
[1,] 2 2 2 4.5 4.5
[2,] 7 7 7 9.5 9.5
[3,] 12 12 12 14.5 14.5
mat <- matrix(1:100e6, ncol = 100)
groups <- rep(1:10, each = 10)
## Map solution
for (i in 1:3){
print(system.time({
mat.list <- Map(matrix, split(mat, groups[col(mat)]), nrow = nrow(mat))
mean.list <- Map(rowMeans, mat.list)
ans1 <- do.call(cbind, mean.list[groups])
}))
}
user system elapsed
8.20 1.26 9.66
user system elapsed
11.84 1.94 13.90
user system elapsed
10.70 1.89 12.79
## rowsum solution
for (i in 1:3){
print(system.time({
means <- rowsum(t(mat), groups)/tabulate(groups)
ans2 <- t(means)[,groups]
}))
}
user system elapsed
1.56 0.22 1.78
user system elapsed
1.48 0.27 1.74
user system elapsed
1.57 0.14 1.72