2016-06-20 3 views
5

Если так вы задаете нестандартный заказ на sort/sort! на Julia DataFrames?Эффективный пользовательский заказ в Julia DataFrames?

julia> using DataFrames 

julia> srand(1); 

julia> df = DataFrame(x = rand(10), y = rand([:high, :med, :low], 10)) 
10×2 DataFrames.DataFrame 
│ Row │ x   │ y │ 
├─────┼────────────┼──────┤ 
│ 1 │ 0.236033 │ med │ 
│ 2 │ 0.346517 │ high │ 
│ 3 │ 0.312707 │ high │ 
│ 4 │ 0.00790928 │ med │ 
│ 5 │ 0.488613 │ med │ 
│ 6 │ 0.210968 │ med │ 
│ 7 │ 0.951916 │ low │ 
│ 8 │ 0.999905 │ low │ 
│ 9 │ 0.251662 │ high │ 
│ 10 │ 0.986666 │ med │ 

julia> sort!(df, cols=[:y]) 
10×2 DataFrames.DataFrame 
│ Row │ x   │ y │ 
├─────┼────────────┼──────┤ 
│ 1 │ 0.346517 │ high │ 
│ 2 │ 0.312707 │ high │ 
│ 3 │ 0.251662 │ high │ 
│ 4 │ 0.951916 │ low │ 
│ 5 │ 0.999905 │ low │ 
│ 6 │ 0.236033 │ med │ 
│ 7 │ 0.00790928 │ med │ 
│ 8 │ 0.488613 │ med │ 
│ 9 │ 0.210968 │ med │ 
│ 10 │ 0.986666 │ med │ 

Я хотел бы иметь y колонку упорядоченную с :low первым, а затем :med и :high. Какой был бы лучший способ сделать это? Я знаю, что я могу сделать следующее:

julia> subdfs = [] 
0-element Array{Any,1} 

julia> for val in [:low, :med, :high] 
      push!(subdfs, df[df[:y] .== val, :]) 
     end 

julia> vcat(subdfs...) 
10×2 DataFrames.DataFrame 
│ Row │ x   │ y │ 
├─────┼────────────┼──────┤ 
│ 1 │ 0.951916 │ low │ 
│ 2 │ 0.999905 │ low │ 
│ 3 │ 0.236033 │ med │ 
│ 4 │ 0.00790928 │ med │ 
│ 5 │ 0.488613 │ med │ 
│ 6 │ 0.210968 │ med │ 
│ 7 │ 0.986666 │ med │ 
│ 8 │ 0.346517 │ high │ 
│ 9 │ 0.312707 │ high │ 
│ 10 │ 0.251662 │ high │ 

Есть ли способ сделать это без выделения памяти, так как в моем конкретном примере, df довольно велика?

ответ

4

Вы можете определить функцию сравнения:

lmhlt(x, y) = x == :low && y != :low || x == :med && y == :high 

Затем используйте

sort!(df, lt=lmhlt) 

Однако, это по-прежнему выделяет память. Однако он должен быть меньше вашей текущей версии.

+1

Ницца! Благодаря! Мне пришлось искать в [docs] (http://docs.julialang.org/en/latest/stdlib/sort/), чтобы полностью понять аргумент 'lt' здесь. Они сказали: «Все функции, связанные с сортировкой и порядком, зависят от отношения« меньше », определяющего общий порядок над значениями, которые нужно манипулировать. Функция' isless' вызывается по умолчанию, но отношение может быть задано через 'lt 'keyword." –

0

Я написал a function to generalize custom sorting многократным колонку просто указать для каждого столбца, которые требуют сортировки на заказ заказ:

Pkg.clone("https://github.com/sylvaticus/LAJuliaUtils.jl.git") 
using DataFrames, LAJuliaUtils 
df = DataFrame(
    c1 = ['a','b','c','a','b','c'], 
    c2 = ["aa","aa","bb","bb","cc","cc"], 
    c3 = [1,2,3,10,20,30], 
) 
customSort!(df, [(:c2,["bb","cc"]),(:c1,['b','a','c'])]) 

6×3 DataFrames.DataFrame 
│ Row │ c1 │ c2 │ c3 │ 
├─────┼─────┼──────┼────┤ 
│ 1 │ 'a' │ "bb" │ 10 │ 
│ 2 │ 'c' │ "bb" │ 3 │ 
│ 3 │ 'b' │ "cc" │ 20 │ 
│ 4 │ 'c' │ "cc" │ 30 │ 
│ 5 │ 'b' │ "aa" │ 2 │ 
│ 6 │ 'a' │ "aa" │ 1 │ 

Вы можете получить более подробную информацию после установки пакета с помощью ?customSort!

Функция использует внутренне sort!() DataFrames работает с ключевым словом by по сравнению с OrderedDict, созданным на основе пользовательского заказа, предложенного пользователем Tamas_Papp по адресу Julia Discourse.

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