[英]Multiply rows of matrix by vector?
我有一個 25 列 23 行的數字matrix
和一個長度為 25 的向量。如何在不使用for
循環的情況下將矩陣的每一行乘以向量?
結果應該是一個 25x23 的矩陣(與輸入的大小相同),但每一行都乘以向量。
從@hatmatrix 的回答中添加了可重現的示例:
matrix <- matrix(rep(1:3,each=5),nrow=3,ncol=5,byrow=TRUE)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 2 2 2 2
[3,] 3 3 3 3 3
vector <- 1:5
期望的輸出:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 2 4 6 8 10
[3,] 3 6 9 12 15
我認為您正在尋找sweep()
。
# Create example data and vector
mat <- matrix(rep(1:3,each=5),nrow=3,ncol=5,byrow=TRUE)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 1 1 1
[2,] 2 2 2 2 2
[3,] 3 3 3 3 3
vec <- 1:5
# Use sweep to apply the vector with the multiply (`*`) function
# across columns (See ?apply for an explanation of MARGIN)
sweep(mat, MARGIN=2, vec, `*`)
[,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 2 4 6 8 10
[3,] 3 6 9 12 15
它一直是 R 的核心功能之一,盡管多年來已經對其進行了改進。
> MyMatrix <- matrix(c(1,2,3, 11,12,13), nrow = 2, ncol=3, byrow=TRUE)
> MyMatrix
[,1] [,2] [,3]
[1,] 1 2 3
[2,] 11 12 13
> MyVector <- c(1:3)
> MyVector
[1] 1 2 3
您可以使用:
> t(t(MyMatrix) * MyVector)
[,1] [,2] [,3]
[1,] 1 4 9
[2,] 11 24 39
或:
> MyMatrix %*% diag(MyVector)
[,1] [,2] [,3]
[1,] 1 4 9
[2,] 11 24 39
實際上, sweep
並不是我電腦上最快的選項:
MyMatrix <- matrix(c(1:1e6), ncol=1e4, byrow=TRUE)
MyVector <- c(1:1e4)
Rprof(tmp <- tempfile(),interval = 0.001)
t(t(MyMatrix) * MyVector) # first option
Rprof()
MyTimerTranspose=summaryRprof(tmp)$sampling.time
unlink(tmp)
Rprof(tmp <- tempfile(),interval = 0.001)
MyMatrix %*% diag(MyVector) # second option
Rprof()
MyTimerDiag=summaryRprof(tmp)$sampling.time
unlink(tmp)
Rprof(tmp <- tempfile(),interval = 0.001)
sweep(MyMatrix ,MARGIN=2,MyVector,`*`) # third option
Rprof()
MyTimerSweep=summaryRprof(tmp)$sampling.time
unlink(tmp)
Rprof(tmp <- tempfile(),interval = 0.001)
t(t(MyMatrix) * MyVector) # first option again, to check order
Rprof()
MyTimerTransposeAgain=summaryRprof(tmp)$sampling.time
unlink(tmp)
MyTimerTranspose
MyTimerDiag
MyTimerSweep
MyTimerTransposeAgain
這產生:
> MyTimerTranspose
[1] 0.04
> MyTimerDiag
[1] 40.722
> MyTimerSweep
[1] 33.774
> MyTimerTransposeAgain
[1] 0.043
除了是最慢的選項之外,第二個選項達到了內存限制 (2046 MB)。 但是,考慮到其余選項,在我看來,雙換位似乎比sweep
要好得多。
編輯
只是重復嘗試較小的數據:
MyMatrix <- matrix(c(1:1e3), ncol=1e1, byrow=TRUE)
MyVector <- c(1:1e1)
n=100000
[...]
for(i in 1:n){
# your option
}
[...]
> MyTimerTranspose
[1] 5.383
> MyTimerDiag
[1] 6.404
> MyTimerSweep
[1] 12.843
> MyTimerTransposeAgain
[1] 5.428
為了速度,可以在乘法之前從向量創建矩陣
mat <- matrix(rnorm(1e6), ncol=1e4)
vec <- c(1:1e4)
mat * matrix(vec, dim(mat)[1], length(vec))
library(microbenchmark)
microbenchmark(
transpose = t(t(mat) * vec),
make_matrix = mat * matrix(vec, dim(mat)[1], length(vec), byrow = TRUE),
sweep = sweep(mat,MARGIN=2,vec,`*`))
#Unit: milliseconds
# expr min lq mean median uq max neval cld
# transpose 9.940555 10.480306 14.39822 11.210735 16.19555 77.67995 100 b
#make_matrix 5.556848 6.053933 9.48699 6.662592 10.74121 74.14429 100 a
# sweep 8.033019 8.500464 13.45724 12.331015 14.14869 77.00371 100 b
這些使用outer()
或collapse::TRA()
解決方案比這里建議的任何方法都快得多。
如果你想要速度,你可以使用Rfast::eachrow
。 它是最快的...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.