如何将一个矩阵的每一行与 R 中的另一个矩阵相乘?

How to multiple each row of one matrix with another matrix in R?

对于下面两个矩阵,

yy=matrix(c(1:40), nrow = 10, ncol = 8)
tt=diag(1:4)

我想通过将 yy 的每一行和第一个 4 column 乘以 tt 来创建一个新矩阵 yy_new=matrix(NA, nrow = 10, ncol=ncol(tt)) 。例如,对于第一行 yy_new=yy[1,1:4]%*%tt,第二行是 yy_new=yy[2,1:4]%*%tt。最后,我希望每列的 yy_new 的平均值为 yy_new=apply(yy_new,2,mean)。以下循环运行良好,但对于大型数据集来说,它是耗时的。

 yy_new=matrix(NA, nrow = 10, ncol=ncol(tt))         
 for ( it in 1:10){
      for ( tim in 1:4){
        yy_new[it, tim]=yy[it,tim]*tt[tim,tim]
      }
    }
yy_new=apply(yy_new,2,mean)

类似地,考虑到 yy

的最后四列,我想要另一个矩阵 yy_new1
 yy_new1=matrix(NA, nrow = 10, ncol=ncol(tt))

如何使用任何内置函数或自定义函数高效地完成它? 感谢任何帮助。

这是 yy_new

的更短(更快)版本
yy_new <- rowMeans(apply(yy[, 1:4], 1, function(row) row %*% tt))

yy

的最后 4 列类似
yy_new1 <- rowMeans(apply(yy[, (ncol(yy)-3):ncol(yy)], 1, function(row) row %*% tt))

请注意 rowMeanscolMeans 通常比 apply(..., 1, mean)apply(..., 2, mean) 快。


这是 microbenchmark 比较的结果

library(microbenchmark)
res <- microbenchmark(
    rowMeans_apply = {
        yy_new = rowMeans(apply(yy[, 1:4], 1, function(row) row %*% tt))
    },
    for_loop = {
        yy_new=matrix(NA, nrow = 10, ncol=ncol(tt))
         for ( it in 1:10){
              for ( tim in 1:4){
                yy_new[it, tim]=yy[it,tim]*tt[tim,tim]
              }
            }
    }
)
res
#Unit: microseconds
#           expr      min       lq      mean   median       uq       max neval
# rowMeans_apply   73.148   82.097  116.8959  101.329  123.863  1348.141   100
#       for_loop 3985.521 4141.633 5017.9808 4421.285 5020.425 18574.364   100

更新

为了回应您的评论,您可以这样做:

f <- function(x) rowMeans(apply(x, 1, function(row) row %*% tt))
sapply(split.default(as.data.frame(yy), rep(1:2, each = 4)), f)
#         1     2
#[1,]   5.5   5.5
#[2,]  31.0  31.0
#[3,]  76.5  76.5
#[4,] 142.0 142.0

说明:split.default这里将data.frame拆分为前4列和后4列,分别存储为两个data.frame在一个list中;然后我们使用 sapply 循环遍历 list 元素并根据要求计算所需数量。生成的输出对象是 matrix.