2010-09-04 27 views
56

Estoy optimizando una función y quiero deshacerme de la lentitud de los bucles. Estoy buscando una manera más rápida de multiplicar cada fila de una matriz por un vector.¿Multiplicar filas de matriz por vector?

¿Alguna idea?

EDIT:

No estoy buscando una multiplicación 'clásico'.

Ej. Tengo una matriz que tiene 23 columnas y 25 filas y un vector que tiene una longitud de 23. En un resultado quiero tener la matriz 25x23 que tiene cada fila multiplicada por el vector.

Respuesta

58

Creo que estás buscando 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 

Ha sido una de las principales funciones de R, aunque se han realizado mejoras a lo largo de los años.

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 

Se puede usar ya sea:

> t(t(MyMatrix) * MyVector) 
    [,1] [,2] [,3] 
[1,] 1 4 9 
[2,] 11 24 39 

o:

> MyMatrix %*% diag(MyVector) 
    [,1] [,2] [,3] 
[1,] 1 4 9 
[2,] 11 24 39 
-2

Google rendimientos "R matriz multiplcation" Matrix Multiplication, que describe el operador% *% y dice "Multiplica dos matrices , si son conformes. Si un argumento es un vector, se promoverá a una matriz de fila o columna para hacer que los dos argumentos sean conformes. Si ambos son vectores, devolverá la p interna. roduct (como una matriz) ".

+2

La cuestión no era – MHH

21

En realidad, sweep no es la opción más rápida en mi equipo:

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 

Esto produce:

> MyTimerTranspose 
[1] 0.04 
> MyTimerDiag 
[1] 40.722 
> MyTimerSweep 
[1] 33.774 
> MyTimerTransposeAgain 
[1] 0.043 

Además de ser la opción más lenta, la segunda opción alcanza el límite de memoria (2046 MEGABYTE). Sin embargo, considerando las opciones restantes, la doble transposición parece mucho mejor que sweep en mi opinión.


Editar

Sólo tratando de datos más pequeños un número repetido de veces: "? ¿Cómo multiplicar una matriz por un vector"

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

En mi experiencia, si lanzas un montón de 'NA's en la matriz, el tiempo tomado por' diag' parece ir por las nubes. Para una estera 1E4x1E4 que contiene 1E5 'NA's, obtengo:' MyTimerTranspose' = 0.014, 'MyTimerSweep' = 0.042,' MyTimerDiag' = 67.738. Me gustaría replicar, pero estoy impaciente ... solo algo a tener en cuenta. – jbaums

+0

Me gusta mucho la doble respuesta de transposición, principalmente porque muestra cuál es la respuesta si reemplazamos "fila" por "columna", lo que hace que la respuesta sea trivial A * x, lo cual no es obvio a menos que realmente comprenda cómo funciona R matrices. – MHH

Cuestiones relacionadas