2017-07-26 91 views
3

我试图将一个自定义的排序算法应用到一堆子数据框中以便绘制一些图。随着this question的帮助下,我能到我的数据框使用自定义排序顺序:为SubDataFrame自定义排序

julia> using DataFrames 

julia> df = DataFrame(x = rand(10), y = rand([:low, :med, :high], 10), z = rand([:a, :b], 10)) 
10×3 DataFrames.DataFrame 
│ Row │ x   │ y │ z │ 
├─────┼───────────┼──────┼───┤ 
│ 1 │ 0.436891 │ low │ b │ 
│ 2 │ 0.370725 │ high │ b │ 
│ 3 │ 0.521269 │ low │ b │ 
│ 4 │ 0.071102 │ high │ a │ 
│ 5 │ 0.969407 │ high │ a │ 
│ 6 │ 0.0416023 │ med │ b │ 
│ 7 │ 0.63486 │ med │ b │ 
│ 8 │ 0.4352 │ high │ b │ 
│ 9 │ 0.626739 │ low │ b │ 
│ 10 │ 0.151149 │ low │ a │ 

julia> o = [:low, :med, :high] 
3-element Array{Symbol,1}: 
:low 
:med 
:high 

julia> custom_sort(x,y) = findfirst(o, x) < findfirst(o, y) 
custom_sort (generic function with 1 method) 

julia> sort!(df, cols=[:y], lt=custom_sort) 
10×3 DataFrames.DataFrame 
│ Row │ x   │ y │ z │ 
├─────┼───────────┼──────┼───┤ 
│ 1 │ 0.436891 │ low │ b │ 
│ 2 │ 0.521269 │ low │ b │ 
│ 3 │ 0.626739 │ low │ b │ 
│ 4 │ 0.151149 │ low │ a │ 
│ 5 │ 0.0416023 │ med │ b │ 
│ 6 │ 0.63486 │ med │ b │ 
│ 7 │ 0.370725 │ high │ b │ 
│ 8 │ 0.071102 │ high │ a │ 
│ 9 │ 0.969407 │ high │ a │ 
│ 10 │ 0.4352 │ high │ b │ 

和它的伟大工程。麻烦的是,当我再做groupby(),自定义排序丢失:

julia> groupby(df, [:y, :z]) 
DataFrames.GroupedDataFrame 5 groups with keys: Symbol[:y, :z] 
First Group: 
2×3 DataFrames.SubDataFrame{Array{Int64,1}} 
│ Row │ x  │ y │ z │ 
├─────┼──────────┼──────┼───┤ 
│ 1 │ 0.071102 │ high │ a │ 
│ 2 │ 0.969407 │ high │ a │ 
⋮ 
Last Group: 
2×3 DataFrames.SubDataFrame{Array{Int64,1}} 
│ Row │ x   │ y │ z │ 
├─────┼───────────┼─────┼───┤ 
│ 1 │ 0.0416023 │ med │ b │ 
│ 2 │ 0.63486 │ med │ b │ 

有没有一种方法我可以SubDataFrame有几分使得例如。第一组是y == :lowz == a

回答

2

groupby利用PooledArray机制将DataFrame分成组。当从矢量创建PooledArray时,顺序不会保留......除非在PooledArray构造函数中指定。通过将列按照所需的顺序放入PooledArrays中,可以欺骗groupby。在代码:

julia> df[:y] = PooledDataArray(df[:y],[:low,:med,:high]) 

julia> df[:z] = PooledDataArray(df[:z],[:a,:b]) 

julia> groupby(df, [:y, :z]) 
DataFrames.GroupedDataFrame 6 groups with keys: Symbol[:y, :z] 
First Group: 
1×3 DataFrames.SubDataFrame{Array{Int64,1}} 
│ Row │ x  │ y │ z │ 
├─────┼──────────┼─────┼───┤ 
│ 1 │ 0.833255 │ low │ a │ 
⋮ 
Last Group: 
1×3 DataFrames.SubDataFrame{Array{Int64,1}} 
│ Row │ x  │ y │ z │ 
├─────┼──────────┼──────┼───┤ 
│ 1 │ 0.604117 │ high │ b │ 

这也可以自动化为多个列或列与多个值与下面的循环:

for v in [:y,:z] 
    df[v] = PooledDataArray(df[v],unique(Vector(df[v]))) 
end 

它执行相同的显式分配早。

+0

大概我需要在使用循环创建'PooledDataArray'之前对需要它的任何列进行自定义排序? – kevbonham

+0

@kevbonham是的。实际上,似乎应该能够根据'groupby'中所需的顺序对列进行排序,并将这些列合并。之后,将数据框以不同的顺序排序,然后执行“groupby”。 –

+0

太棒了,该作品了!谢谢! – kevbonham