在R中,可以通过在两个%*%
和M1: n x p
之间使用M2: p x d
来执行叉积,这两个矩阵的一维长度相同。
要对M1中的每一行1..n
和M2中的第1..d列乘以相对乘积p_M1 x p_M2
,然后求和向量相加。
但我希望得到的积不是prod(p_M1 x p_M2)
。
我可以使用R中的嵌套循环来执行此操作,但是它非常慢并且我的矩阵很大。有没有像%*%
一样快的替代方案?
示例:
set.seed(1)
a <- matrix(sample((1:100) / 100, 15), ncol = 3)
b <- matrix(sample((1:100) / 100, 15), ncol = 5)
# This produces the usual cross-product...
a %*% b
# ...which can be done also using loops
do.call('cbind', lapply(1:5, function(i) {
sapply(1:5, function(j) {
sum(a[i,] * b[,j])
})
}))
# But I need to do the product of the paired vectors instead of the sum. I could use a nested loop but it takes hours.
do.call('cbind', lapply(1:5, function(i) {
sapply(1:5, function(j) {
prod(a[i,] * b[,j])
})
}))
答案 0 :(得分:6)
在我的评论之后,这是一个带有matrixStats
软件包和outer
的方法来执行计算。
# nested loop
mat1 <-
do.call('cbind', lapply(1:5, function(i) {
sapply(1:5, function(j) {
prod(a[i,] * b[,j])
})
}))
# vectorized-ish
library(matrixStats)
mat2 <- outer(colProds(b), rowProds(a))
现在,检查它们在数值上是否相等。
all.equal(mat1, mat2)
[1] TRUE
如果您想要%*%
的外观,可以将其更改为
mat2 <- colProds(b) %o% rowProds(a)
如果要避免包装,可以坚持以R为底。这是一种方法。
mat3 <- outer(
vapply(seq_len(ncol(b)), function(x) prod(b[, x]), numeric(1L)),
vapply(seq_len(nrow(a)), function(x) prod(a[x, ]), numeric(1L))
))
测试这两个的速度,我得到以下结果
library(microbenchmark)
microbenchmark(nest=
do.call('cbind', lapply(1:5, function(i) {
sapply(1:5, function(j) {
prod(a[i,] * b[,j])
})
})),
vect=outer(colProds(b), rowProds(a)),
baseVect=outer(
vapply(seq_len(ncol(b)), function(x) prod(b[, x]), numeric(1L)),
vapply(seq_len(nrow(a)), function(x) prod(a[x, ]), numeric(1L))
))
Unit: microseconds
expr min lq mean median uq max neval
nest 129.228 133.2225 172.43874 136.833 142.9640 3531.144 100
vect 23.831 25.8690 28.38306 27.705 29.1815 94.546 100
baseVect 27.223 29.8970 57.85946 31.471 32.8400 2647.373 100