很抱歉,如果这看起来微不足道,但在网上搜索了一段时间后,我无法找到解决方案。
我有一个矩阵和一个与列相关的因子向量。目标是分别为所有因子获取rowMeans并保持原始矩阵结构。所以可能它会像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,] 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
实际上,这个矩阵将有数百万行(和更少的列)。因此,逐行工作的解决方案可能太慢了。
我正在编写自己的函数,但这似乎可能是一个简单的单行解决方案。
答案 0 :(得分:3)
1)假设您要将每行的每个元素替换为该行的平均值,请尝试将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))
答案 1 :(得分:2)
也许是这样的:
mat.list <- Map(matrix, split(mat, groups[col(mat)]), nrow = nrow(mat))
mean.list <- Map(rowMeans, mat.list)
do.call(cbind, mean.list[groups])
或者为了更快的速度:
idx.list <- split(seq_len(ncol(mat)), groups)
get.cols <- function(mat, idx) mat[, idx, drop = FALSE]
mat.list <- lapply(idx.list, get.cols, mat = mat)
mean.list <- lapply(mat.list, rowMeans)
do.call(cbind, mean.list[groups])
答案 2 :(得分:1)
如果有一个优化的功能,比如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
这可以很好地适应更大的问题,例如
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
正如已经指出的那样,ave
解决方案无法很好地扩展 - 当我尝试为此运行时间时,我的R会话崩溃了。