2010-09-04 8 views
56

Я оптимизирую функцию, и я хочу избавиться от медленных циклов. Я ищу более быстрый способ умножить каждую строку матрицы на вектор.Умножить строки матрицы по вектору?

Любые идеи?

EDIT:

Я не ищу для 'классического' умножения.

Например. У меня есть матрица, которая имеет 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

Google "R матрица multiplcation" дает Matrix Multiplication, описывающую% *% оператора и говорит «Перемножает две матрицы , если они являются совместимыми.Если один аргумент является вектором, он будет продвигаться либо к матрице строк или столбцов, чтобы сделать два аргумента совместимыми. Если оба являются векторами, он вернет внутренний p (как матрица) ".

+2

Вопрос был не – MHH

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', похоже, пройдет через крышу. Для мата 1E4x1E4, содержащего 1E5 'NA', я получаю: 'MyTimerTranspose' = 0.014,' MyTimerSweep' = 0.042, 'MyTimerDiag' = 67.738. Я бы реплицировал, но я нетерпелив ... просто что-то нужно иметь в виду. – jbaums

+0

Мне очень нравится ответ на двойной транспозиции, главным образом потому, что он показывает, что ответ, если мы заменим «строку» на «столбец», что дает ответ на тривиальный A * x, что не очевидно, если вы действительно не понимаете, как работает R матрицы. – MHH

Смежные вопросы