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))