How to calculate the product from combinations of several vectors in R?

  • A+
Category:Languages

I feel it hard to give an accurate title, though I have tried my best. Here's my problem.

a = 1/(1:10) b = 3/(1:10) c = 1/(1:5) d = 1/(1:11) 

I would like to get a vector e, such that e consists of the product calculated from the combinations of values chosen from a, b, c and d.

For example, supposing there are two vectors {1, 2} and {3, 4}, I would like to get a vector like this {1 * 3, 1 * 4, 2 * 3, 2 * 4} = {3, 4, 6, 8}.

Thanks in advance!

 


The expand.grid solution is OK, but in mathematics there is an elegant Kronecker product.

R has a function kronecker, but it takes two vectors at a time, so we need Reduce for a recursive application:

oo <- Reduce(kronecker, list(a, b, c, d)) 

Alternatively, use outer (the workhorse of kronecker):

rr <- Reduce(outer, list(a, b, c, d)) 

This is more user-friendly, as rr[i, j, u, v] gives you a[i] * b[j] * c[u] * d[v].


Remark 1

Note that elements in oo and rr differ in order. Because for two vectors a and b:

kronecker(a, b)  ## a[1] * b, a[2] * b ... outer(a, b)      ## a * b[1], a * b[2] ... 

Thus the following use of kronecker produces a result identical to rr.

zz <- Reduce(kronecker, list(d, c, b, a)) dim(zz) <- c(length(a), length(b), length(c), length(d)) 

Remark 2

The method can be adapted to do a[i] + b[j] + c[u] + d[v], by replacing the default operation "*" in outer and kronecker to "+". For example:

Reduce(function (x, y) outer(x, y, "+"), list(a, b, c, d)) 

Remark 3

johannes's answer can be improved. That row-wise application of apply is a performance killer. We can do the following to get a result consistent with rr.

xx <- Reduce("*", expand.grid(a, b, c, d)) dim(xx) <- c(length(a), length(b), length(c), length(d)) 

Comment

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: