Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Broadcasting in R

Tags:

arrays

r

numpy

(I come from python, that's why my question has kind of a pythonian style)

I have a matrix x (str(x)-> num[1:1000,1:4]) and a vector y (str(y) -> num[1:4]). I want to subtract from each column of x the coreespoonding entry in y. I.e. x_y[i] = x[,i]-y[i].

The way I found to do this is t(t(x)-y), but in my opinion this is a rather cryptic way. Are there any more reader friendly ways to do this?

For those of you who kno python: I'm essentially searching for a similar way of broadcasting as known in numpy, that alloes to shape the dimensions via np.newaxis etc.

like image 441
Jürg Merlin Spaak Avatar asked Jul 01 '26 21:07

Jürg Merlin Spaak


1 Answers

There are other options as well.

I am using x and y created like this:

x <- matrix(1:4000, ncol = 4)

y <- 1:4

The first one is using sweep(), where 2 is the MARGIN:

sweep(x, 2, y)

Another way is using apply() to loop through the rows of x

apply(x, 2, function(xi, y) {

  xi - y

}, y = y)

If you look at the time to evaluate your option plus the two above, you can see that yours is the fastest.

microbenchmark::microbenchmark(
  t(t(x)-y), 
  apply(x, 2, function(xi, y) {

    xi - y

  }, y = y),
  sweep(x, 2, y),
  times = 1000
)

Outputs:

Unit: microseconds
                                               expr    min      lq      mean  median      uq       max neval
                                        t(t(x) - y) 23.062 24.3390  32.30354 25.6270 27.2205  1044.485  1000
 apply(x, 2, function(xi, y) {     xi - y }, y = y) 67.541 70.6580  96.80288 75.1020 79.7865  1245.883  1000
                                     sweep(x, 2, y) 46.673 50.1955 108.42835 53.0515 57.0315 44158.248  1000

From this you could probably derive that sweep() is a good compromise between performance and readability, but t(t(x) - y) is the fastest.

like image 96
clemens Avatar answered Jul 04 '26 11:07

clemens



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!