pandas GroupBy.agg()を使用した同じ列の複数の集計


127

複数回呼び出す必要なしf1, f2に、2つの異なる集計関数を同じ列に適用するpandas組み込みの方法はありますか?df["returns"]agg()

データフレームの例:

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)
}) 

構文的には間違っていますが、直感的には正しい方法は次のとおりです。

# Assume `f1` and `f2` are defined for aggregating.
df.groupby("dummy").agg({"returns": f1, "returns": f2})

もちろん、Pythonでは重複するキーは許可されていません。への入力を表現する他の方法はありますagg()か?おそらく、タプルのリストは[(column, function)]、同じ列に適用される複数の関数を許可するために、よりうまく機能しますか?しかしagg()、それは辞書しか受け入れないようです。

内部に両方の関数を適用するだけの補助関数を定義する以外に、これに対する回避策はありますか?(とにかく、これは集約でどのように機能しますか?)



2
0.25以降、pandasは複数の集計と出力列の名前変更のためのより直感的な構文を提供します。名前付き集計に関するドキュメントを参照してください。
cs95

参考までに、この質問は
2012

1
受け入れられた回答も参考にしてください-agg()に口述の口述を渡さないでください。
cs95

@ cs95:私はそれが非推奨であることを知っています、私はSOが古いバージョンの古い古いソリューションで散らかっていることを言っています。SOには、コメント以外に、それをマークする方法がありません。
smci

回答:


159

関数をリストとして渡すだけです:

In [20]: df.groupby("dummy").agg({"returns": [np.mean, np.sum]})
Out[20]:         
           mean       sum
dummy                    
1      0.036901  0.369012

または辞書として:

In [21]: df.groupby('dummy').agg({'returns':
                                  {'Mean': np.mean, 'Sum': np.sum}})
Out[21]: 
        returns          
           Mean       Sum
dummy                    
1      0.036901  0.369012

4
結果の列名を指定する方法はありますか?
ベン

3
@Ben後で名前を変更する必要があると思います。Tom Augspurgerによる例(セル25を参照)
Stewbaca

1
@ベン:私は例を追加しました
bmu

10
@sparc_spread複数の関数をリストとして渡す方法については、 pandasのドキュメントで詳しく説明されています。複数の関数の名前を変更して辞書として渡すことは、パンダの将来のバージョンで廃止される予定です。詳細は0.20変更ログにあります。これは、SOの別の場所でまとめました
joelostblom 2017年

3
すでに述べられていますが、年齢から出力列の名前を変更するための辞書の使用は非推奨です。代わりに、タプルのリストを指定できます。この答えを見てください。
cs95

101

TLDR; Pandasにgroupby.aggは、(1)複数の列の集計、および(2)列の複数の集計を指定するための新しい、より簡単な構文があります。したがって、パンダ> = 0.25に対してこれを行うには、次を使用します

df.groupby('dummy').agg(Mean=('returns', 'mean'), Sum=('returns', 'sum'))

           Mean       Sum
dummy                    
1      0.036901  0.369012

または

df.groupby('dummy')['returns'].agg(Mean='mean', Sum='sum')

           Mean       Sum
dummy                    
1      0.036901  0.369012

パンダ> = 0.25:名前付き集約

パンダは、GroupBy.agg名前付き集計を指定するためのより直感的な構文を優先するように動作を変更しました。参照機能強化の0.25ドキュメントのセクションだけでなく、関連するGitHubの問題GH18366GH26512を

ドキュメントから、

出力列名を制御して列固有の集計をサポートするために、pandasはGroupBy.agg()「名前付き集計」と呼ばれるの特別な構文を受け入れます。

  • キーワードは出力列名です
  • 値は、最初の要素が選択する列であり、2番目の要素がその列に適用する集計であるタプルです。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をキーワード引数に渡すだけです。

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

4
新しいバージョンのインターフェイスを使用してより明確でクリーンなソリューションを使用するため、これが一番の答えになるはずです。
NKSHELL

名前付き集計に使用される例は、同じ列で複数の集計を使用するという元の問題を解決しません。たとえば、最初にサブセット化せずに高さの最小値と最大値の両方で集計できますdf.groupby('kind')['height']か?
ビクター

1
@victor質問に直接対処するTLDRを回答の上部に追加しました。そして、2番目の質問に対する答えは「はい」です。私の答えの編集を見てください。
cs95

このように複数の列の集計を処理する> = 0.25の回答の最後の例に対するより一般的なコードは、すばらしいでしょう。 df.groupby("kind").agg(**{ 'max height': pd.NamedAgg(column='height', aggfunc=max), 'min weight': pd.NamedAgg(column='weight', aggfunc=min) })
Onur Ece

6

このようなものでしょうか:

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

2
いいえ、これは機能しません。doc文字列を見ると、aggregatea dictが渡されるとき、キーは列名でなければならないことが明示されています。だからあなたの例はあなたがこのエラーをチェックせずにあなたが入力したものであるか、そうでなければPandasはここで独自のドキュメントを壊します
12

N / MIはreturnsそこへの追加の呼び出しを確認しませんでした。これはシリーズバージョンの集計ですか?DataFrameバージョンの集計を実行しようとしています。複数の異なる集計を各列に一度に適用したいと考えています。
e

1
これを試してください:df.groupby( 'dummy')。agg({'returns':{'func1':lambda x:x.sum()、 'func2':lambda x:x.mean()}})
Chang彼女は

メッセージなしでアサーションエラーが発生します。コードの外観(pandas.core.internals.py、行406-408、バージョン0.7.3)から、最後にチェックを行い、最初のキーよりも多くの列が返されないことを確認しているようです集計辞書のレイヤー。
12

マスターで問題なく動作します。更新してみますか?
Chang She
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.