0

I have been trying to create vectors where each element can take two different values present in two different vectors.
For example, if there are two vectors a and b, where a is c(6,2,9) and b is c(12,5,15) then the output should be 8 vectors given as follows,

6   2   9  
6   2  15  
6   5   9  
6   5  15  
12  2   9  
12  2  15  
12  5   9  
12  5  15  

The following piece of code works,

aa1 <- c(6,12)
aa2 <- c(2,5)
aa3 <- c(9,15)
for(a1 in 1:2)
  for(a2 in 1:2)
   for(a3 in 1:2)
   {
     v <- c(aa1[a1],aa2[a2],aa3[a3])
     print(v)
   }

But I was wondering if there was a simpler way to do this instead of writing several for loops which will also increase linearly with the number of elements the final vector will have.

Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197
user3082806
  • 33
  • 3
  • 10

2 Answers2

1

I think what you're looking for is expand.grid.

a <- c(6,2,9)
b <- c(12,5,15)

expand.grid(a,b)
 Var1 Var2
1    6   12
2    2   12
3    9   12
4    6    5
5    2    5
6    9    5
7    6   15
8    2   15
9    9   15
Ben J
  • 11
  • 1
  • Yes, but you need to pass pairs of elements so the ultimate call is `expand.grid(c(6, 12), c(2, 5), c(9, 15))` (but preferably without hardcoding). – alistaire Aug 22 '16 at 05:28
1

expand.grid is a function that makes all combinations of whatever vectors you pass it, but in this case you need to rearrange your vectors so you have a pair of first elements, second elements, and third elements so the ultimate call is:

expand.grid(c(6, 12), c(2, 5), c(9, 15))

A quick way to rearrange the vectors in base R is Map, the multivariate version of lapply, with c() as the function:

a <- c(6, 2, 9)
b <- c(12, 5, 15)

Map(c, a, b)

## [[1]]
## [1]  6 12
## 
## [[2]]
## [1] 2 5
## 
## [[3]]
## [1]  9 15

Conveniently expand.grid is happy with either individual vectors or a list of vectors, so we can just call:

expand.grid(Map(c, a, b))

##   Var1 Var2 Var3
## 1    6    2    9
## 2   12    2    9
## 3    6    5    9
## 4   12    5    9
## 5    6    2   15
## 6   12    2   15
## 7    6    5   15
## 8   12    5   15

If Map is confusing you, if you put a and b in a list, purrr::transpose will do the same thing, flipping from a list of two elements of length three to a list of three elements of length two:

library(purrr)

list(a, b) %>% transpose() %>% expand.grid()

and return the same thing.

alistaire
  • 42,459
  • 4
  • 77
  • 117