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)
どうすればこれを回避できますか?
apply
を使用してSeriesを返し、列の名前を変更しますGroupby apply
メソッドを使用して、次の集約を実行します。
これをする:
apply
に渡すカスタム関数を作成します偽データの作成
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]})
シリーズを返すカスタム関数を作成します
_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)
大きな欠点は、この関数が cythonized aggregates のagg
よりもはるかに遅いことです。
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
内部辞書をタプルのリストに置き換えると、警告メッセージが削除されます
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")]})
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
これは私がやったことです:
偽のデータセットを作成します。
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
内側の辞書を、正しい名前の関数のリストに置き換えます。
このユーティリティ関数を使用している関数の名前を変更するには:
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