I can't get to make this work, although it seems fairly simple. I would like to multiply every row in matrix (or dataframe or datatable) b, with vector a.
a <- data.table(t(1:4))
b <- matrix(data=2, nrow=3, ncol=4)
Desired output (in matrix, dataframe or datatable form):
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
Can anyone help me how to do this (efficiently)?
b*rep(unlist(a),each=nrow(b))
# [,1] [,2] [,3] [,4]
# [1,] 2 4 6 8
# [2,] 2 4 6 8
# [3,] 2 4 6 8
or just b*rep(a,each=nrow(b)) if you define a <- 1:4
It's just a vectorised element wise multiplication with no transformation appart from rep.
edit:
It seems that rep is what is slowing down my solution. Here's a benchmark where I include an option with precomputed rep, and some improvements on the sweep option (taking only relevant parts from source code).
a <- data.table(t(1:200))
b <- matrix(data=2, nrow=100000, ncol=200)
a_vec <- unlist(a)
rep_a <- rep(a_vec,each=nrow(b))
microbenchmark::microbenchmark(
mkr1 = a[,lapply(.SD,function(x)(x*b[,x]))],
mkr2 = t(t(b) * (as.matrix(a)[1,])),
mkr_update = a[,lapply(V1:V4,function(i)(a[[i]]*b[,i]))],
mm = b*rep(unlist(a),each=nrow(b)),
mm_cheat = b*rep_a,
regular_sweep = sweep(b,2,unlist(a),`*`),
regular_sweep2 = sweep(b,2,a_vec,`*`),
improved_sweepA1 = b*aperm(array(unlist(a),rev(dim(b)))),
improved_sweepA2 = b*aperm(array(a_vec,rev(dim(b)))),
improved_sweepB1 = b*a[rep_len(1,nrow(b)),],
improved_sweepB2 = b*t(a_vec)[rep_len(1,nrow(b)),],
unit = "relative",
times=50)
Unit: relative
expr min lq mean median uq max neval
mkr1 42.12228 44.15266 50.23959 46.35240 57.20280 65.07289 50
mkr2 114.58427 124.19653 125.25660 131.08677 124.17058 114.91137 50
mkr_update 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 50
mm 231.34331 223.74365 217.50145 225.91117 215.90765 165.64814 50
mm_cheat 13.38838 13.22556 14.94682 13.36649 12.95260 25.15564 50
regular_sweep 96.15758 124.26746 121.04428 128.67282 129.19407 119.20210 50
regular_sweep2 97.79001 124.69191 124.74650 134.64249 134.97407 107.47152 50
improved_sweepA1 96.57837 124.86189 116.93736 127.08909 124.92805 105.83318 50
improved_sweepA2 96.27737 122.49773 118.45262 128.13369 126.15029 106.58669 50
improved_sweepB1 214.95773 227.39523 226.04339 248.38553 232.50401 161.45341 50
improved_sweepB2 31.20967 32.61873 37.74552 33.70969 41.52149 55.93362 50
On my side I would use the built-in method of R for Matrix Multiplication %*%.
Considering the vector: [NB: data.table is not vector]
a <- c(1:4)
and considering the matrix:
b <- matrix(data=2, nrow=3, ncol=4)
Your output is given by:
output <- b %*% diag(a)
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
sweep:sweep(b, 2, a, FUN = "*")
[,1] [,2] [,3] [,4]
[1,] 2 4 6 8
[2,] 2 4 6 8
[3,] 2 4 6 8
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With