To find every vector of the form (x, y) where x is drawn from vector X and y from Y, we use `expand.grid`

:

```
X = c(1, 1, 2)
Y = c(4, 5)
expand.grid(X, Y)
# Var1 Var2
# 1 1 4
# 2 1 4
# 3 2 4
# 4 1 5
# 5 1 5
# 6 2 5
```

The result is a data.frame with one column for each vector passed to it. Often, we want to take the Cartesian product of sets rather than to expand a "grid" of vectors. We can use `unique`

, `lapply`

and `do.call`

:

```
m = do.call(expand.grid, lapply(list(X, Y), unique))
# Var1 Var2
# 1 1 4
# 2 2 4
# 3 1 5
# 4 2 5
```

If you then want to apply a function to each resulting combination `f(x,y)`

, it can be added as another column:

```
m$p = with(m, Var1*Var2)
# Var1 Var2 p
# 1 1 4 4
# 2 2 4 8
# 3 1 5 5
# 4 2 5 10
```

This approach works for as many vectors as we need, but in the special case of two, it is sometimes a better fit to have the result in a matrix, which can be achieved with `outer`

:

```
uX = unique(X)
uY = unique(Y)
outer(setNames(uX, uX), setNames(uY, uY), `*`)
# 4 5
# 1 4 5
# 2 8 10
```

For related concepts and tools, see the combinatorics topic.