2010-09-04 134 views
56

我正在优化一个函数,我想摆脱慢循环。 我正在寻找一种更快的方式来乘以一个矢量矩阵的每一行。用矢量乘以矩阵的行吗?

任何想法?

编辑:

我不是在寻找一个'古典'乘法。

例如,我有矩阵,有23列25行和长度为23的矢量。 结果我想要矩阵25x23,每行乘以矢量。

回答

58

我认为你正在寻找sweep()

> (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 
> 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的核心功能之一,虽然多年来已经有所改进。

31
> 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 
-2

谷歌 “R矩阵multiplcation” 产量Matrix Multiplication,描述%*%操作,并表示“将两个矩阵相乘,如果它们是一致的,如果一个参数是一个向量,它将被提升为一个行或列矩阵来使这两个参数一致,如果两个都是向量,它将返回内部的p产品(作为矩阵)“。

+2

问题不 – MHH 2013-12-23 03:34:36

21

其实,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 
+3

根据我的经验,如果你向矩阵中投入一堆“NA”,“diag”所花费的时间似乎要经过屋顶。对于包含1E5'NA's的1E4x1E4垫,我得到:'MyTimerTranspose' = 0.014,'MyTimerSweep' = 0.042,'MyTimerDiag' = 67.738。我会复制,但我不耐烦...只是要记住。 – jbaums 2012-03-01 22:19:51

+0

我真的很喜欢双转换的答案,主要是因为它显示了如果我们用“列”替换“行”,答案是简单的A * x,这是不明显的,除非你真正理解R如何工作矩阵。 – MHH 2013-12-23 03:38:27