Groupby với sum trên Julia Dataframe

Oct 06 2020

Tôi đang cố tạo nhóm bằng + tổng trên Khung dữ liệu Julia với các giá trị Int và Chuỗi

Ví dụ: df:

│ Row │ A      │ B      │ C     │ D      │
│     │ String │ String │ Int64 │ String │
├─────┼────────┼────────┼───────┼────────┤
│ 1   │ x1     │ a      │ 12    │ green  │
│ 2   │ x2     │ a      │ 7     │ blue   │
│ 3   │ x1     │ b      │ 5     │ red    │
│ 4   │ x2     │ a      │ 4     │ blue   │
│ 5   │ x1     │ b      │ 9     │ yellow │

Để thực hiện điều này trong Python, lệnh có thể là:

df_group = df.groupby(['A', 'B']).sum().reset_index()

Tôi sẽ nhận được kết quả đầu ra sau với các nhãn cột ban đầu:

    A  B   C
0  x1  a  12
1  x1  b  14
2  x2  a  11

Tôi muốn làm điều tương tự ở Julia. Tôi đã thử theo cách này, không thành công:

df_group = aggregate(df, ["A", "B"], sum)

MethodError: không có phương thức nào so khớp + (:: String, :: String)

Bạn có bất kỳ ý tưởng nào về cách để làm điều này trong Julia?

Trả lời

2 BogumiłKamiński Oct 06 2020 at 21:12

Hãy thử (thực sự thay vì các cột không phải là chuỗi, có thể bạn muốn các cột là số):

numcols = names(df, findall(x -> eltype(x) <: Number, eachcol(df)))
combine(groupby(df, ["A", "B"]), numcols .=> sum .=> numcols)

và nếu bạn muốn cho phép missingcác giá trị (và bỏ qua chúng khi thực hiện tổng kết) thì:

numcols = names(df, findall(x -> eltype(x) <: Union{Missing,Number}, eachcol(df)))
combine(groupby(df, ["A", "B"]), numcols .=> sum∘skipmissing .=> numcols)
2 AndrejOskin Oct 06 2020 at 21:13

Julia DataFrames hỗ trợ logic phân tách-áp dụng-kết hợp , tương tự như gấu trúc, vì vậy việc tổng hợp trông giống như

using DataFrames

df = DataFrame(:A => ["x1", "x2", "x1", "x2", "x1"], 
               :B => ["a", "a", "b", "a", "b"],
               :C => [12, 7, 5, 4, 9],
               :D => ["green", "blue", "red", "blue", "yellow"])

gdf = groupby(df, [:A, :B])
combine(gdf, :C => sum)

Với kết quả

julia> combine(gdf, :C => sum)
3×3 DataFrame
│ Row │ A      │ B      │ C_sum │
│     │ String │ String │ Int64 │
├─────┼────────┼────────┼───────┤
│ 1   │ x1     │ a      │ 12    │
│ 2   │ x2     │ a      │ 11    │
│ 3   │ x1     │ b      │ 14    │

Bạn có thể bỏ qua quá trình tạo gdfvới sự trợ giúp của Pipe.jl hoặc Underscores.jl

using Underscores

@_ groupby(df, [:A, :B]) |> combine(__, :C => sum)

Bạn có thể đặt tên cho cột mới bằng cú pháp sau

julia> @_ groupby(df, [:A, :B]) |> combine(__, :C => sum => :C)
3×3 DataFrame
│ Row │ A      │ B      │ C     │
│     │ String │ String │ Int64 │
├─────┼────────┼────────┼───────┤
│ 1   │ x1     │ a      │ 12    │
│ 2   │ x2     │ a      │ 11    │
│ 3   │ x1     │ b      │ 14    │