2016-06-20 25 views
5

Czy istnieje szybka metoda określania niestandardowego zamówienia na sort/sort! na Julia DataFrames?Efektywne porządkowanie niestandardowe w 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 │ 

ja jak do kolumny y zamawiać :low najpierw, a następnie :med i :high. Jaki byłby najlepszy sposób na zrobienie tego? Wiem, można wykonać następujące czynności:

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 │ 

Czy istnieje sposób to zrobić bez przydzielania pamięci, ponieważ w moim rzeczywisty przykład df jest dość duży?

Odpowiedz

4

Można zdefiniować funkcję porównania:

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

Następnie użyj

sort!(df, lt=lmhlt) 

to jednak nadal przydziela pamięć. Powinien być jednak mniejszy niż twoja obecna wersja.

+1

Nice! Dzięki! Musiałem szukać w [docs] (http://docs.julialang.org/en/latest/stdlib/sort/), aby w pełni zrozumieć argument "lt" tutaj. Powiedzieli: "Wszystkie funkcje związane z sortowaniem i porządkami opierają się na relacji" mniej niż "określającej całkowitą kolejność wartości, które mają być manipulowane. Funkcja' isless' jest domyślnie wywoływana, ale relację można określić za pomocą 'lt 'słowo kluczowe." –

0

pisałem a function to generalize custom sorting do wielokrotnego kolumnie po prostu określając dla każdej kolumny, które wymagają sortowania kolejność niestandardowe:

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 │ 

można uzyskać więcej szczegółów po zainstalowaniu pakietu używając ?customSort!

Funkcja wykorzystuje wewnętrznie sort!() DataFrames działa ze słowem kluczowym by nad OrderedDict zbudowanym na podstawie dostarczonego przez użytkownika zamówienia niestandardowego, zgodnie z sugestią użytkownika Tamas_Papp na Julia Discourse.