Группировка с суммой в кадре данных Julia

#dataframe #group-by #julia #aggregate

#фрейм данных #группировать по #julia #агрегировать

Вопрос:

Я пытаюсь создать groupby sum в фрейме данных Julia со значениями Int и String

Например, df :

 │ Row │ AB      │ C     │ D      │
│     │ String │ String │ Int64 │ String │
├─────┼────────┼────────┼───────┼────────┤
│ 1   │ x1     │ a12    │ green  │
│ 2   │ x2     │ a7     │ blue   │
│ 3   │ x1     │ b5     │ red    │
│ 4   │ x2     │ a4     │ blue   │
│ 5   │ x1     │ b9     │ yellow │
  

Чтобы сделать это в Python, команда может быть :

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

Я получу следующий результат вывода с начальными метками столбцов :

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

Я хотел бы сделать то же самое в Julia. Я пробовал этот способ, безуспешно :

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

Ошибка метода: нет соответствия метода (::String, ::String)

Есть ли у вас какие-либо идеи о том, как это сделать в Julia?

Ответ №1:

Попробуйте (на самом деле вместо нестроковых столбцов, вероятно, вам нужны числовые столбцы):

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

и если вы хотите разрешить missing значения (и пропустить их при выполнении суммирования), то:

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

Комментарии:

1. Спасибо за ответ. На практике в моем реальном фрейме данных много столбцов для суммирования ( 100). Поэтому я хотел бы найти более общий способ сделать. Возможно ли сделать сумму по всем нестроковым столбцам?

2. Это возможно на master (так что оно будет доступно в версии 0.22). Я обновлю ответ рекомендацией, которую можно использовать сейчас.

Ответ №2:

Фреймы данных Julia поддерживают логику разделения-применения-объединения, аналогичную pandas, поэтому агрегирование выглядит следующим образом

 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)
  

с результатом

 julia> combine(gdf, :C => sum)
3×3 DataFrameRowABC_sum │
│     │ StringStringInt64 │
├─────┼────────┼────────┼───────┤
│ 1x1a12    │
│ 2x2a11    │
│ 3x1b14 

Вы можете пропустить создание gdf с помощью Pipe.jl или подчеркивания.jl

 using Underscores

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

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

 julia> @_ groupby(df, [:A, :B]) |> combine(__, :C => sum => :C)
3×3 DataFrameRowABC     │
│     │ StringStringInt64 │
├─────┼────────┼────────┼───────┤
│ 1x1a12    │
│ 2x2a11    │
│ 3x1b14 

Комментарии:

1. Спасибо за ваш ответ.

2. что, если я хочу выполнить групповую сумму и подсчитать в одной строке?