2010-09-04 12 views
56

Sto ottimizzando una funzione e voglio liberarmi di cicli lenti. Sto cercando un modo più veloce per moltiplicare ogni riga di una matrice con un vettore.Moltiplica le righe di matrice per vettore?

Qualche idea?

EDIT:

Io non sto cercando una moltiplicazione 'classica'.

Es. Ho una matrice che ha 23 colonne e 25 righe e un vettore che ha una lunghezza di 23. In un risultato voglio avere una matrice 25x23 che ha ogni riga moltiplicata per vettore.

risposta

58

Penso che stiate cercando 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 

È stata una delle funzioni principali di R, anche se nel corso degli anni sono stati apportati miglioramenti.

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 

Si potrebbe utilizzare:

> 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 "R matrice multiplcation" rendimenti Matrix Multiplication, che descrive l'% * operatore% e dice "Moltiplica due matrici se sono conformi, se un argomento è un vettore, sarà promosso a una matrice o a una matrice di colonne per rendere i due argomenti conformi. Se entrambi sono vettori restituirà l'interno p rodotto (come una matrice). "

+2

La domanda non è stata – MHH

21

In realtà, sweep non è l'opzione più veloce sul mio computer:

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 

Questo produce:

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

Oltre ad essere l'opzione più lenta, la seconda opzione raggiunge il limite di memoria (2046 MB). Tuttavia, considerando le opzioni rimanenti, la doppia trasposizione sembra molto meglio di sweep a mio parere.


Modifica

Solo cercando di dati più piccoli una serie ripetuta di volte: "come si fa a moltiplicare una matrice per un vettore"

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

Secondo la mia esperienza, se lanci un mucchio di 'NA' nella matrice, il tempo impiegato da' diag' sembra passare attraverso il tetto. Per un supporto 1E4x1E4 contenente 1E5 'NA's, ottengo:' MyTimerTranspose' = 0.014, 'MyTimerSweep' = 0.042,' MyTimerDiag' = 67.738. Mi piacerebbe replicare, ma sono impaziente ... solo qualcosa da tenere a mente. – jbaums

+0

Mi piace molto la doppia risposta di trasposizione, principalmente perché mostra quale è la risposta se sostituiamo "row" con "column", rendendo la risposta banale A * x, che non è ovvio a meno che non capiate veramente come funziona R con matrici. – MHH

Problemi correlati