Wiele agregacji tej samej kolumny za pomocą pandy GroupBy.agg()
Czy jest wbudowany sposób na zastosowanie dwóch różnych funkcji agregujących f1, f2
do tej samej kolumny df["returns"]
, bez konieczności wielokrotnego wywoływania agg()
?
Przykładowa ramka danych:
import pandas as pd
import datetime as dt
pd.np.random.seed(0)
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)
})
Składniowo błędnym, ale intuicyjnie właściwym sposobem na to byłoby:
# Assume `f1` and `f2` are defined for aggregating.
df.groupby("dummy").agg({"returns": f1, "returns": f2})
Oczywiście Python nie pozwala na duplikowanie kluczy. Czy jest jakiś inny sposób na wyrażenie wejścia do agg()
? Być może Lista krotek [(column, function)]
byłaby lepsza, aby umożliwić wielokrotne funkcje zastosowane do tej samej kolumny? Ale wygląda na to, że akceptuje tylko słownik.
Czy istnieje obejście tego problemu poza zdefiniowaniem funkcji pomocniczej, która po prostu stosuje obie funkcje wewnątrz niego? (Jak to w ogóle działa z agregacją?)
3 answers
Możesz po prostu przekazać funkcje jako listę:
In [20]: df.groupby("dummy").agg({"returns": [np.mean, np.sum]})
Out[20]:
mean sum
dummy
1 0.036901 0.369012
Lub jako słownik:
In [21]: df.groupby('dummy').agg({'returns':
{'Mean': np.mean, 'Sum': np.sum}})
Out[21]:
returns
Mean Sum
dummy
1 0.036901 0.369012
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-08 09:16:31
TLDR; Pandas groupby.agg
ma nową, łatwiejszą składnię do określania (1) agregacji na wielu kolumnach i (2) Wielu agregacji na kolumnie. Więc, aby to zrobić dla pand >= 0.25, użyj
df.groupby('dummy').agg(Mean=('returns', 'mean'), Sum=('returns', 'sum'))
Mean Sum
dummy
1 0.036901 0.369012
Lub
df.groupby('dummy')['returns'].agg(Mean='mean', Sum='sum')
Mean Sum
dummy
1 0.036901 0.369012
Pandy > = 0.25: Nazwane Agregacje
Pandy zmieniły zachowanie GroupBy.agg
na rzecz bardziej intuicyjnej składni do określania nazw agregacji. Zobacz sekcję 0.25 docs na temat ulepszeń, a także istotne Problemy z githubem GH18366 i GH26512 .
Z dokumentacji,
Do obsługi agregacji specyficznej dla kolumn z kontrolą nad wyjściem nazwy kolumn, pandy przyjmują specjalną składnię w
GroupBy.agg()
, znane jako "named aggregation", gdzie
- słowa kluczowe są nazwami kolumn wyjściowych
- wartości są krotkami, których pierwszym elementem jest kolumna do wybrania, a drugim element jest agregacja do zastosowania do tej kolumny. Pandy zapewniają pandy.NamedAgg namedtuple with the fields ['column', 'aggfunc'] aby było jasne, jakie są argumenty. Jako Zwykle agregacja może być aliasem wywoływalnym lub ciągiem znaków.
Można teraz przekazać krotkę za pomocą argumentów słów kluczowych. Krotki mają format (<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
Alternatywnie, możesz użyć pd.NamedAgg
(zasadniczo nazwastuple), co czyni rzeczy bardziej wyraźnymi.
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
Jest jeszcze prostsze dla serii, wystarczy przejść aggfunc do argumentu słowa kluczowego.
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
Na koniec, jeśli nazwy kolumn nie są poprawnymi identyfikatorami Pythona, użyj słownika z rozpakowaniem:
df.groupby('kind')['height'].agg(**{'max height': 'max', ...})
Pandy
W nowszych wersjach pand prowadzących do 0.24, jeśli używasz słownika do określania nazw kolumn dla wyjścia agregacji, otrzymasz 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
Używanie słownika do zmiany nazw kolumn jest przestarzałe w wersji 0.20. w nowszych wersjach pand, może to być określa się po prostu poprzez podanie listy krotek. W przypadku określenia funkcji w ten sposób, wszystkie funkcje dla tej kolumny muszą być określone jako krotki par (nazwa, funkcja).
df.groupby("dummy").agg({'returns': [('op1', 'sum'), ('op2', 'mean')]})
returns
op1 op2
dummy
1 0.328953 0.032895
Lub
df.groupby("dummy")['returns'].agg([('op1', 'sum'), ('op2', 'mean')])
op1 op2
dummy
1 0.328953 0.032895
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-08 09:34:11
Czy coś takiego działa:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-26 01:30:08