2015-02-22 2 views
4

expand.grid - очень удобная функция в R для расчета всех возможных комбинаций нескольких списков. Вот как это работает:Воспроизведение функции `expand.grid` от R в Julia

> 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 

Как воспроизвести эту функцию в Юлии?

+0

Я думал о создании 'n' вложенных циклов, где' n' является число переменных (3 : 'x',' y', 'z' в моем примере выше). Каждый цикл будет перебирать количество уникальных значений в каждой переменной, но я запутался, потому что не знаю заранее, сколько циклов мне нужно. Поэтому я думал о создании функции, которая называет себя, но 1) я не знаю, возможно ли это в Julia и 2), которая звучит как глупо сложное решение, которое, вероятно, не будет очень перфорированным. Спасибо за ваш комментарий. –

+0

Вы видели, как R expand.grid это делает? Он зацикливается на количестве аргументов, добавляя столбец на каждой итерации, который является извилистым подмножеством исходного столбца со всеми видами вложенных rep и т. Д. ... – Spacedman

+1

Проверьте [** здесь **] (http: // www .scolvin.com/juliabyexample /): «' repeat' может быть полезен для расширения сетки, как в функции 'expand.grid() в R, и [** здесь **] (http://stackoverflow.com/ Вопросы/23581263/is-there-outer-map-function-in-julia): «Есть ли какая-то функция аналога' expand.grid' из R "(первые два хита google ...) – Henrik

ответ

2

Благодаря @ комментарий Хенрика:

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

Вот еще одно решение, используя список понимание

reshape([ [x,y,z] for x=x, y=y, z=z ],length(x)*length(y)*length(z)) 
+0

Следует учитывать, что для первого требуется пакет, а второй - специальный для конечного набора списков (хотя это нормально для любого конкретного случая) – IainDunning

+0

Да, действительно! Я добавил «использование итераторов». Спасибо! –

2

Вот мой полностью общее решение, используя рекурсию, переменной длины, и 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 

Это дает массив массивов, но вы могли бы объединить, что в матрицу тривиальным, если тот, что вы хотели ,

Смежные вопросы