Умножение строки матрицы на вектор?
я оптимизирую функцию и хочу избавиться от медленных циклов. Я ищу более быстрый способ умножения каждой строки матрицы на вектор.
какие идеи?
EDIT:
Я не ищу "классическое" умножение.
например. У меня есть матрица, которая имеет 23 столбца и 25 строк и вектор, который имеет длину 23. В результате я хочу иметь матрицу 25x23, которая имеет каждую строку, умноженную на вектор.
3 ответа:
Я думаю, что вы ищете
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, хотя на протяжении многих лет были сделаны улучшения.
> 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 МБ). Однако, учитывая остальные варианты,двойной транспозиции кажется, намного лучше, чем
sweep
по-моему.
Edit
просто пробуя меньшие данные повторное число раз:
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