2

抱歉,如果这看起来微不足道,但在互联网上搜索了一段时间后,我无法找到解决方案。

我有一个矩阵和一个与列关联的因子向量。目标是分别获取所有因子的 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

在实践中,这个矩阵将有数百万行(和更少的列)。因此,逐行工作的解决方案可能太慢了。

我正在编写自己的函数,但这似乎有一个简单的单行解决方案。

4

3 回答 3

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))
于 2014-10-14T23:34:53.030 回答
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])
于 2014-10-15T00:16:03.133 回答
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 会话崩溃了。

于 2014-10-15T13:37:29.030 回答