Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Automatic multiplication between vector and matrix

Tags:

r

I have this R code:

> coef
[1] 1.5 2.4 3.9 4.4
> y
     [,1] [,2] [,3] [,4]
[1,]    1    2   12   45
[2,]    5    6    7    8
[3,]    9   10    2   12
[4,]   13   14   15   45
[5,]   17   18   39    7

I have to multiply each value of the column with the respective coef. The result should be:

First column:
1*1.5 
5*1.5 
9*1.5 
13*1.5 
17*1.5

Second column: 
2*2.4 
6*2.4 
10*2.4 
14*2.4 
18*2.4

Third column: 
12*3.9 
7*3.9 
2*3.9 
15*3.9 
39*3.9

Fourth column: 
45*4.4
8*4.4
12*4.4 
45*4.4 
7*4.4

All the column's values moltiplied by the same coefficient at the same index in the vector.

How can I do this calculation?

The solution could be:

> y[,1] <- y[,1] * coef[1]
> y[,2] <- y[,2] * coef[2]
> y[,3] <- y[,3] * coef[3]
> y[,4] <- y[,4] * coef[4]

But doesn't seem too optimized! Something better?

Thank you!

like image 929
Bleak Avatar asked Nov 29 '22 16:11

Bleak


2 Answers

This will give you what you want:

t( t(y) * coef  )
like image 75
Prasad Chalasani Avatar answered Dec 02 '22 05:12

Prasad Chalasani


Two more possibilities: sweep and scale (the latter only operates columnwise, and seems to me to be a bit of hack).

coef <- c(1.5,2.4,3.9,4.4)
y <- matrix(c(seq(1,17,by=4),
              seq(2,18,by=4),
              c(12,7,2,15,39,
                45,8,12,45,7)),
              ncol=4)

t(t(y)*coef)
t(apply(y,1,"*",coef))
sweep(y,2,coef,"*")
scale(y,center=FALSE,scale=1/coef)

library(rbenchmark)

benchmark(t(t(y)*coef),
           y %*% diag(coef),
           t(apply(y,1,"*",coef)),
           sweep(y,2,coef,"*"),
           scale(y,center=FALSE,scale=1/coef),
           replications=1e4)

                                      test replications elapsed relative
5 scale(y, center = FALSE, scale = 1/coef)        10000   0.990 4.342105
4                   sweep(y, 2, coef, "*")        10000   0.846 3.710526
3                t(apply(y, 1, "*", coef))        10000   1.537 6.741228
1                           t(t(y) * coef)        10000   0.228 1.000000
2                         y %*% diag(coef)        10000   0.365 1.600877

edit: added y %*% diag(coef) from @baptiste [not fastest, although it might be so for a big problem with a sufficiently optimized BLAS package ...] [and it was fastest in another trial, so I may just not have had a stable estimate]

edit: fixed typo in t(t(y)*coef) [thanks to Timur Shtatland] (but did not update timings, so they might be slightly off ...)

I also tried library(Matrix); y %*% Diagonal(x=coef), which is very slow for this example but might be fast for a large matrix (??). (I also tried constructing the diagonal matrix just once, but even multiplication by a predefined matrix was slow in this example (25x slower than the best, vs. 47x slower when defining the matrix on the fly.)

I have a mild preference for sweep as I think it expresses most clearly the operation being done ("multiply the columns by the elements of coef")

like image 40
Ben Bolker Avatar answered Dec 02 '22 06:12

Ben Bolker