Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reproduce the `expand.grid` function from R in Julia

expand.grid is a very handy function in R for calculating all possible combinations of several list. Here is how it works:

> x = c(1,2,3)
> y = c("a","b")
> z = c(10,12)
> d = expand.grid(x,y,z)
> d
   Var1 Var2 Var3
1     1    a   10
2     2    a   10
3     3    a   10
4     1    b   10
5     2    b   10
6     3    b   10
7     1    a   12
8     2    a   12
9     3    a   12
10    1    b   12
11    2    b   12
12    3    b   12

How can I reproduce this function in Julia?

like image 990
Remi.b Avatar asked Feb 22 '15 20:02

Remi.b


People also ask

What is the expand grid() function in R?

What is the expand.grid () function? It is a function in R’s Base system, meaning that it is already there when you install R for the first time, and does not even require any additional package to be installed. From the function’s documentation, it “Create a Data Frame from All Combinations of Factor Variables”.

What does the function expand_grid() do in tidyr?

From the function’s documentation, it “Create a Data Frame from All Combinations of Factor Variables”. There is also a more recent adaptation of it into a tidyr::expand_grid () one, which takes care of some annoying side effects, and also allows expanding data.frames.

Why can’t I use r commands in Julia?

For example, ggplot R commands such as don’t translate directly to Julia code because the . in na.rm is interpreted as Julia syntax. Similar issues arise if, for instance, an R function uses end as an argument name. The solution to this problem is to use the var string macro provided by RCall, which enables us to write

Why can’t I use ggplot in Julia?

For example, ggplot R commands such as don’t translate directly to Julia code because the . in na.rm is interpreted as Julia syntax. Similar issues arise if, for instance, an R function uses end as an argument name.


2 Answers

Thanks to @Henrik's comment:

x = [1,2,3]
y = ["a","b"]
z = [10,12]
d = collect(Iterators.product(x,y,z))

Here is another solution using list comprehension

reshape([ [x,y,z]  for x=x, y=y, z=z ],length(x)*length(y)*length(z))
like image 51
Remi.b Avatar answered Sep 27 '22 14:09

Remi.b


Here is my completely(?) general solution, using recursion, varargs, and splatting:

function expandgrid(args...)
    if length(args) == 0
        return Any[]
    elseif length(args) == 1
        return args[1]
    else
        rest = expandgrid(args[2:end]...)
        ret  = Any[]
        for i in args[1]
            for r in rest
                push!(ret, vcat(i,r))
            end
        end
        return ret
    end
end

eg = expandgrid([1,2,3], ["a","b"], [10,12])
@assert length(eg) == 3*2*2
@show eg

This gives an array of arrays, but you could combine that into a matrix trivially if thats what you wanted.

like image 23
IainDunning Avatar answered Sep 23 '22 14:09

IainDunning