78 votes

Multiplier les lignes de la matrice par un vecteur?

J'optimise une fonction et je veux me débarrasser des boucles lentes. Je cherche un moyen plus rapide de multiplier chaque ligne d'une matrice par un vecteur.

Des idées?

MODIFIER:

Je ne cherche pas une multiplication "classique".

Par exemple. J'ai matrice qui a 23 colonnes et 25 lignes et un vecteur qui a une longueur de 23. Dans un résultat, je veux avoir une matrice 25x23 qui a chaque ligne multipliée par vecteur.

93voto

crippledlambda Points 8422

Je pense que vous recherchez 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
 

C'est l'une des fonctions principales de R, même si des améliorations ont été apportées au fil des ans.

45voto

Wok Points 2020
 > 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
 

Vous pouvez utiliser soit:

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

ou:

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

28voto

Wok Points 2020

En fait, sweep n'est pas l'option la plus rapide sur mon ordinateur:

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

Cela donne:

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

En plus d'être l'option la plus lente, la deuxième option atteint la limite de la mémoire (2046 MO). Toutefois, considérant le reste des options, la double transposition semble beaucoup mieux que sweep à mon avis.


Modifier

Juste en essayant de données plus petite a répété nombre de fois:

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

0voto

John R. Strohm Points 5338

La "multiplication matricielle R" de Google donne la multiplication matricielle , qui décrit l'opérateur% *% et dit: "Multiplie deux matrices, si elles sont conformes. Si un argument est un vecteur, il sera promu en matrice de rangées ou de colonnes pour deux arguments conformes. Si les deux sont des vecteurs, le produit interne sera renvoyé (sous forme de matrice). "

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X