Несколько агрегатов одного столбца с использованием pandas GroupBy.agg()
Учитывая следующий (полностью перебитый) пример фрейма данных
import pandas as pd
import datetime as dt
df = pd.DataFrame({
"date" : [dt.date(2012, x, 1) for x in range(1, 11)],
"returns" : 0.05 * np.random.randn(10),
"dummy" : np.repeat(1, 10)
})
Существует ли существующий встроенный способ применения двух разных функций агрегирования к одному и тому же столбцу без необходимости многократного вызова agg
?
Синтаксически неправильный, но интуитивно правильный способ сделать это:
# Assume 'function1' and 'function2' are defined for aggregating.
df.groupby("dummy").agg({"returns":function1, "returns":function2})
Очевидно, что Python не позволяет дублировать ключи. Есть ли другой способ выражения ввода в agg
? Возможно, список кортежей [(column, function)]
будет работать лучше, чтобы несколько функций применялись к одному столбцу? Но похоже, что он принимает только словарь.
Есть ли обходной путь для этого помимо определения вспомогательной функции, которая просто применяет обе функции внутри нее? (Как это будет работать с агрегацией?)
Ответы
Ответ 1
Вы можете просто передать функции в виде списка:
In [20]: df.groupby("dummy").agg({"returns": [np.mean, np.sum]})
Out[20]:
returns
sum mean
dummy
1 0.285833 0.028583
или как словарь:
In [21]: df.groupby('dummy').agg({'returns':
{'Mean': np.mean, 'Sum': np.sum}})
Out[21]:
returns
Sum Mean
dummy
1 0.285833 0.028583
Ответ 2
Что-то вроде этой работы:
In [7]: df.groupby('dummy').returns.agg({'func1' : lambda x: x.sum(), 'func2' : lambda x: x.prod()})
Out[7]:
func2 func1
dummy
1 -4.263768e-16 -0.188565
Ответ 3
Pandas изменил поведение GroupBy.agg
в пользу более интуитивного синтаксиса для указания именованных агрегатов. См. Раздел 0.25 документации по улучшениям, а также соответствующие выпуски GitHub GH18366 и GH26512.
Из документации,
Для поддержки агрегирования по конкретным столбцам с контролем над именами выходных столбцов pandas принимает специальный синтаксис в GroupBy.agg()
, известный как "именованная агрегация", где
- Ключевыми словами являются имена выходных столбцов.
- Значения - это кортежи, первый элемент которых является столбцом для выбора, а второй элемент является агрегацией, применяемой к этому столбцу. Pandas предоставляет pandas.NamedAgg namedtuple с полями ['column', 'aggfunc'], чтобы прояснить аргументы. Как обычно, агрегация может быть вызываемым или строковым псевдонимом.
Теперь вы можете передать кортеж через аргументы ключевых слов. Кортежи следуют формату (<colName>, <aggFunc>)
.
import pandas as pd
pd.__version__
# '0.25.0.dev0+840.g989f912ee'
# Setup
df = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'],
'height': [9.1, 6.0, 9.5, 34.0],
'weight': [7.9, 7.5, 9.9, 198.0]
})
df.groupby('kind').agg(
max_height=('height', 'max'), min_weight=('weight', 'min'),)
max_height min_weight
kind
cat 9.5 7.9
dog 34.0 7.5
Кроме того, вы можете использовать pd.NamedAgg
(по сути, именованный кортеж), который делает вещи более явными.
df.groupby('kind').agg(
max_height=pd.NamedAgg(column='height', aggfunc='max'),
min_weight=pd.NamedAgg(column='weight', aggfunc='min')
)
max_height min_weight
kind
cat 9.5 7.9
dog 34.0 7.5
Для Series это еще проще, просто передайте aggfunc ключевому слову arguments.t
df.groupby('kind')['height'].agg(max_height='max', min_height='min')
max_height min_height
kind
cat 9.5 9.1
dog 34.0 6.0
Наконец, если ваши имена столбцов не являются допустимыми идентификаторами Python, используйте словарь с распаковкой:
df.groupby('kind')['height'].agg(**{'max height': 'max', ...})
Панды <0,25
В более поздних версиях панд, ведущих к значению 0,24, при использовании словаря для указания имен столбцов для вывода агрегации вы получите FutureWarning
:
df.groupby('dummy').agg({'returns': {'Mean': 'mean', 'Sum': 'sum'}})
# FutureWarning: using a dict with renaming is deprecated and will be removed
# in a future version
Использование словаря для переименования столбцов устарело в v0.20. В более поздних версиях панд это можно указать проще, передав список кортежей. При указании функций таким способом все функции для этого столбца должны быть указаны в виде кортежей пар (имя, функция).
df.groupby("dummy").agg({'returns': [('op1', 'sum'), ('op2', 'mean')]})
returns
op1 op2
dummy
1 0.328953 0.032895
Или же,
df.groupby("dummy")['returns'].agg([('op1', 'sum'), ('op2', 'mean')])
op1 op2
dummy
1 0.328953 0.032895