2016-06-20 8 views
5

Gibt es eine schnelle Methode zum Angeben einer benutzerdefinierten Bestellung an Julia DataFrames zu sort/sort!?Effiziente benutzerdefinierte Reihenfolge in 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 │ 

Ich mag würde die y Spalte mit :low zuerst von :med und :high gefolgt bestellt haben. Was wäre der beste Weg, dies zu tun? Ich weiß, ich kann folgendes tun:

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 │ 

Gibt es eine Möglichkeit, dies zu tun, ohne da das Zuweisen von Speicher in meinem eigentlichen Beispiel ist df recht groß?

Antwort

4

Sie können eine Vergleichsfunktion definieren:

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

Dann wird dieser noch Speicher reserviert jedoch

sort!(df, lt=lmhlt) 

verwenden. Es sollte jedoch weniger als Ihre aktuelle Version sein.

+1

Schön! Vielen Dank! Ich musste in der [docs] (http://docs.julaulang.org/en/latest/stdlib/sort/) suchen, um das 'lt' Argument hier zu verstehen. Sie sagten: "Alle sortier- und auftragsbezogenen Funktionen beruhen auf einer Beziehung" kleiner als ", die eine Gesamtordnung der zu manipulierenden Werte definiert. Die Funktion" isless "wird standardmäßig aufgerufen, aber die Beziehung kann über die 'lt 'Schlüsselwort." –

0

Ich schrieb a function to generalize custom sorting auf mehrere Spalte nur für jede Spalte angeben, die die kundenspezifischen Auftrag benötigen Sortierung:

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 │ 

können Sie mehr Details einmal bekommen das Paket ?customSort!

Die Funktion verwendet intern die sort!() mit installiert DataFrames funktionieren mit dem Schlüsselwort by über eine , die auf der vom Benutzer bereitgestellten benutzerdefinierten Bestellung basiert, wie vom Benutzer Tamas_Papp unter Julia Discourse vorgeschlagen.