Джулия: Сделайте Dataframe из вывода итератора

Я пытаюсь создать фрейм данных в Julia с двумя столбцами, x и y, представляющими декартово произведение значений x и значений y. Я думаю, что вкратце это можно описать как использование вывода итератора, двумерного массива кортежей, в качестве аргумента для DataFrame.

Вот код для получения массива кортежей продукта (Julia 1.4.2):

x = [0:0.1:2;]
y = [0:1.5:30;]
product = collect(Iterators.product(x, y))

Я хочу что-то вроде этого:

    x         y 
    Float64  Float64    
1   0.0      0.0    
2   0.1      1.5    
3   0.2      3.0    
4   0.3      4.5    
5   0.4      6.0    
6   0.5      7.5    

Большое спасибо за внимание.

См. также:  Разработка языковых привязок с помощью xtensor
Понравилась статья? Поделиться с друзьями:
IT Шеф
Комментарии: 3
  1. zazizoma

    Декартово произведение — это набор упорядоченных кортежей, поэтому фактически Iterators.product в этом случае возвращает матричный итератор по кортежам, т.е. вызов collect на Iterators.product(x,y) вернет Matrix{Tuple{Float64,Float64}}

    Но конструктор DataFrame может съесть итератор в качестве аргумента и вернуть желаемый результат.

    x = 0:0.1:2
    y = 0:1.5:30
    product = Iterators.product(x, y)
    df = DataFrame(product)
    rename!(df, [:x, :y])
    

    Обратите внимание, что вы не можете указать имена df в конструкторе, например DataFrame(product, [:x, :y]), потому что такого метода нет

    Большое спасибо за ваше решение. Особенно понравился итератор eat. person zazizoma; 08.07.2020

  2. zazizoma

    На самом деле это даже проще. Просто пиши:

    julia> rename!(DataFrame(vec(product)), [:x, :y])
    441×2 DataFrame
    │ Row │ x       │ y       │
    │     │ Float64 │ Float64 │
    ├─────┼─────────┼─────────┤
    │ 1   │ 0.0     │ 0.0     │
    │ 2   │ 0.1     │ 0.0     │
    ⋮
    │ 439 │ 1.8     │ 30.0    │
    │ 440 │ 1.9     │ 30.0    │
    │ 441 │ 2.0     │ 30.0    │
    

    Еще один хороший шаблон для двух столбцов:

    julia> flatten(DataFrame(x=x, y=Ref(y)), :y)
    441×2 DataFrame
    │ Row │ x       │ y       │
    │     │ Float64 │ Float64 │
    ├─────┼─────────┼─────────┤
    │ 1   │ 0.0     │ 0.0     │
    │ 2   │ 0.0     │ 1.5     │
    ⋮
    │ 439 │ 2.0     │ 27.0    │
    │ 440 │ 2.0     │ 28.5    │
    │ 441 │ 2.0     │ 30.0    │
    

    Если вы используете Iterators.product, не материализуя его сначала, это будет немного быстрее, а материализация Iterators.product будет самой быстрой (но использует немного больше памяти):

    julia> @benchmark rename!(DataFrame(Iterators.product($x, $y)), [:x, :y])
    BenchmarkTools.Trial:
      memory estimate:  10.98 KiB
      allocs estimate:  56
      --------------
      minimum time:     9.400 μs (0.00% GC)
      median time:      10.000 μs (0.00% GC)
      mean time:        13.129 μs (8.31% GC)
      maximum time:     5.644 ms (99.56% GC)
      --------------
      samples:          10000
      evals/sample:     1
    
    julia> @benchmark flatten(DataFrame(x=$x, y=Ref($y)), :y)
    BenchmarkTools.Trial:
      memory estimate:  17.72 KiB
      allocs estimate:  80
      --------------
      minimum time:     10.299 μs (0.00% GC)
      median time:      11.300 μs (0.00% GC)
      mean time:        14.268 μs (7.56% GC)
      maximum time:     5.400 ms (99.58% GC)
      --------------
      samples:          10000
      evals/sample:     1
    
    julia> @benchmark rename!(DataFrame(vec(collect(Iterators.product($x, $y)))), [:x, :y])
    BenchmarkTools.Trial:
      memory estimate:  18.03 KiB
      allocs estimate:  58
      --------------
      minimum time:     6.600 μs (0.00% GC)
      median time:      7.160 μs (0.00% GC)
      mean time:        9.286 μs (11.73% GC)
      maximum time:     1.104 ms (98.91% GC)
      --------------
      samples:          10000
      evals/sample:     5
    
  3. zazizoma

    Вы можете использовать Ranges прямо в конструкторе DataFrame:

    julia> using DataFrames
    
    julia> df = DataFrame(x=0:0.1:2, y=0:1.5:30)
    21×2 DataFrame
    │ Row │ x       │ y       │
    │     │ Float64 │ Float64 │
    ├─────┼─────────┼─────────┤
    │ 1   │ 0.0     │ 0.0     │
    │ 2   │ 0.1     │ 1.5     │
    │ 3   │ 0.2     │ 3.0     │
    │ 4   │ 0.3     │ 4.5     │
    │ 5   │ 0.4     │ 6.0     │
    │ 6   │ 0.5     │ 7.5     │
    ⋮
    │ 20  │ 1.9     │ 28.5    │
    │ 21  │ 2.0     │ 30.0    │
    

    Спасибо, но это не дает мне всех комбинаций x и y, и я ожидаю 441 строку, а не 21. person zazizoma; 07.07.2020

    Извините, я просмотрел ваш пример вывода, где значения были сопоставлены в соответствующих парах, и я подумал, что это то, что вы хотите — в этом случае используйте ответ Богумила, здесь нечего добавлять. person zazizoma; 07.07.2020

Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: