Multiply Permutations of Two Vectors in R

Multiply permutations of two vectors in R

Use outer(A,B,'*') which will return a matrix

x<-c(1:4)
y<-c(10:14)
outer(x,y,'*')

returns

     [,1] [,2] [,3] [,4] [,5]
[1,] 10 11 12 13 14
[2,] 20 22 24 26 28
[3,] 30 33 36 39 42
[4,] 40 44 48 52 56

and if you want the result in a list you then can do

z<-outer(x,y,'*')
z.list<-as.list(t(z))

head(z.list) returns

[[1]]
[1] 10

[[2]]
[1] 11

[[3]]
[1] 12

[[4]]
[1] 13

[[5]]
[1] 14

[[6]]
[1] 20

which is x1*y1, x1*y2, x1* y3, x1*y4, x2*y1 ,... (if you want x1*y1, x2*y1, ... replace t(z) by z)

Multiplying vector combinations

You are probably looking for outer() or it's alias binary operator %o%:

> c(2,3,4) %o% c(1,2)
[,1] [,2]
[1,] 2 4
[2,] 3 6
[3,] 4 8
> outer(c(2,3,4), c(1,2))
[,1] [,2]
[1,] 2 4
[2,] 3 6
[3,] 4 8

In your case, outer() offers the flexibility to specify a function that is applied to the combinations; %o% only applies the * multiplication function. For your example and data

mph <- function(d, rpm) {
cir <- pi * d
cir * rpm / 63360 * 60
}

> outer(c(20,26,29), c(150,350), FUN = mph)
[,1] [,2]
[1,] 8.924979 20.82495
[2,] 11.602473 27.07244
[3,] 12.941220 30.19618

Product between all combinations of a vector's elements

We can use combn with anonymous function call

combn(vec, 2, FUN = function(x) x[1] * x[2])
#[1] 2 3 4 6 8 12

data

vec <- 1:4

multiplying each value in one vector to all values in a second vector and creating a results matrix

What you are looking for is outer.

outer(x, y, FUN = "*")

If you want to use plus instead of multiplication you can change * to ·+·

outer(x, y, FUN = "+")

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

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

Pasting two vectors with combinations of all vectors' elements

You can use this, but there may be a simpler solution :

R> apply(expand.grid(vars, vis), 1, paste, collapse=".")
[1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"

expand.grid gives back a data.frame which when used with apply, apply will convert it to a matrix. This is just unnecessary (and inefficient on large data). outer gives a matrix and also takes function argument. It'll be much efficient on huge data as well.

Using outer:

as.vector(outer(vars, vis, paste, sep="."))
# [1] "SR.1" "PL.1" "SR.2" "PL.2" "SR.3" "PL.3"

Combinations of multiple vectors in R

This is a useful case for storing the vectors in a list and using do.call() to arrange for an appropriate function call for you. expand.grid() is the standard function you want. But so you don't have to type out or name individual vectors, try:

> l <- list(a = 1:2, b = 3:4, c = 2:3)
> do.call(expand.grid, l)
a b c
1 1 3 2
2 2 3 2
3 1 4 2
4 2 4 2
5 1 3 3
6 2 3 3
7 1 4 3
8 2 4 3

However, for all my cleverness, it turns out that expand.grid() accepts a list:

> expand.grid(l)
a b c
1 1 3 2
2 2 3 2
3 1 4 2
4 2 4 2
5 1 3 3
6 2 3 3
7 1 4 3
8 2 4 3


Related Topics



Leave a reply



Submit