如何将一个矩阵的每一行与 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))
请注意 rowMeans
和 colMeans
通常比 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
.
对于下面两个矩阵,
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
yy_new1 <- rowMeans(apply(yy[, (ncol(yy)-3):ncol(yy)], 1, function(row) row %*% tt))
请注意 rowMeans
和 colMeans
通常比 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
.