web-dev-qa-db-ja.com

Pandas集約の結果列の名前を変更します(「FutureWarning:名前変更を伴うdictの使用は非推奨」)

pandasデータフレームでいくつかの集計を実行しようとしています。サンプルコードを次に示します。

import pandas as pd

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]})

df.groupby(["User"]).agg({"Amount": {"Sum": "sum", "Count": "count"}})

Out[1]: 
      Amount      
         Sum Count
User              
user1   18.0     2
user2   20.5     3
user3   10.5     1

次の警告が生成されます。

FutureWarning:名前を変更して辞書を使用することは推奨されておらず、将来のバージョンでは削除されます。super(DataFrameGroupBy、self).aggregate(arg、* args、** kwargs)

どうすればこれを回避できますか?

41
Victor Mayrink

Groupby applyを使用してSeriesを返し、列の名前を変更します

Groupby applyメソッドを使用して、次の集約を実行します。

  • 列の名前を変更します
  • 名前にスペースを含めることができます
  • 選択した方法で返された列を並べ替えることができます
  • 列間の相互作用を可能にします
  • MultiIndexではなく、単一レベルのインデックスを返します

これをする:

  • applyに渡すカスタム関数を作成します
  • このカスタム関数は、各グループにDataFrameとして渡されます
  • シリーズを返す
  • シリーズのインデックスは新しい列になります

偽データの作成

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1", "user3"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0, 9],
                  'Score': [9, 1, 8, 7, 7, 6, 9]})

enter image description here

シリーズを返すカスタム関数を作成します
_my_agg内の変数xはDataFrameです

def my_agg(x):
    names = {
        'Amount mean': x['Amount'].mean(),
        'Amount std':  x['Amount'].std(),
        'Amount range': x['Amount'].max() - x['Amount'].min(),
        'Score Max':  x['Score'].max(),
        'Score Sum': x['Score'].sum(),
        'Amount Score Sum': (x['Amount'] * x['Score']).sum()}

    return pd.Series(names, index=['Amount range', 'Amount std', 'Amount mean',
                                   'Score Sum', 'Score Max', 'Amount Score Sum'])

このカスタム関数をgroupby applyメソッドに渡します

df.groupby('User').apply(my_agg)

enter image description here

大きな欠点は、この関数が cythonized aggregatesaggよりもはるかに遅いことです。

Groupby aggメソッドで辞書を使用する

辞書の辞書の使用は、その複雑さとやや曖昧な性質のため削除されました。 githubで今後この機能を改善する方法について 継続中の議論 があります。ここでは、groupby呼び出しの後に集約列に直接アクセスできます。適用したいすべての集約関数のリストを渡すだけです。

df.groupby('User')['Amount'].agg(['sum', 'count'])

出力

       sum  count
User              
user1  18.0      2
user2  20.5      3
user3  10.5      1

Otherという名前の別の数値列があった場合のように、辞書を使用して、列ごとに異なる集計を明示的に示すこともできます。

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
              "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0],
              'Other': [1,2,3,4,5,6]})

df.groupby('User').agg({'Amount' : ['sum', 'count'], 'Other':['max', 'std']})

出力

      Amount       Other          
         sum count   max       std
User                              
user1   18.0     2     6  3.535534
user2   20.5     3     5  1.527525
user3   10.5     1     4       NaN
72
Ted Petrou

内部辞書をタプルのリストに置き換えると、警告メッセージが削除されます

import pandas as pd

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]})

df.groupby(["User"]).agg({"Amount": [("Sum", "sum"), ("Count", "count")]})
11
Jacob Stevenson

Pandas 0.25+の更新 集計の再ラベル付け

import pandas as pd

print(pd.__version__)
#0.25.0

df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0]})

df.groupby("User")['Amount'].agg(Sum='sum', Count='count')

出力:

        Sum  Count
User              
user1  18.0      2
user2  20.5      3
user3  10.5      1
3
Scott Boston

これは私がやったことです:

偽のデータセットを作成します。

import pandas as pd
df = pd.DataFrame({"User": ["user1", "user2", "user2", "user3", "user2", "user1", "user3"],
                  "Amount": [10.0, 5.0, 8.0, 10.5, 7.5, 8.0, 9],
                  'Score': [9, 1, 8, 7, 7, 6, 9]})
df

O/P:

    Amount  Score   User
0   10.0    9   user1
1   5.0 1   user2
2   8.0 8   user2
3   10.5    7   user3
4   7.5 7   user2
5   8.0 6   user1
6   9.0 9   user3

最初にUserをインデックスにし、次にgroupbyを作成しました。

ans = df.set_index('User').groupby(level=0)['Amount'].agg([('Sum','sum'),('Count','count')])
ans

解決:

    Sum Count
User        
user1   18.0    2
user2   20.5    3
user3   19.5    2
2

内側の辞書を、正しい名前の関数のリストに置き換えます。

このユーティリティ関数を使用している関数の名前を変更するには:

def aliased_aggr(aggr, name):
    if isinstance(aggr,str):
        def f(data):
            return data.agg(aggr)
    else:
        def f(data):
            return aggr(data)
    f.__= name
    return f

Group-byステートメントは次のようになります。


df.groupby(["User"]).agg({"Amount": [ 
    aliased_aggr("sum","Sum"),
    aliased_aggr("count","Count")
]

より大きく再利用可能な集約仕様がある場合は、次のように変換できます。

def convert_aggr_spec(aggr_spec):
    return {
        col : [ 
            aliased_aggr(aggr,alias) for alias, aggr in aggr_map.items() 
        ]  
        for col, aggr_map in aggr_spec.items() 
    }

だからあなたは言うことができます

df.groupby(["User"]).agg(convert_aggr_spec({"Amount": {"Sum": "sum", "Count": "count"}}))

参照 https://github.com/pandas-dev/pandas/issues/18366#issuecomment-476597674

0
plankthom