次のデータフレームを検討してください:
A B C D
0 foo one 0.162003 0.087469
1 bar one -1.156319 -1.526272
2 foo two 0.833892 -1.666304
3 bar three -2.026673 -0.322057
4 foo two 0.411452 -0.954371
5 bar two 0.765878 -0.095968
6 foo one -0.654890 0.678091
7 foo three -1.789842 -1.130922
次のコマンドが機能します。
> df.groupby('A').apply(lambda x: (x['C'] - x['D']))
> df.groupby('A').apply(lambda x: (x['C'] - x['D']).mean())
しかし、次の作業はどれも行われません。
> df.groupby('A').transform(lambda x: (x['C'] - x['D']))
ValueError: could not broadcast input array from shape (5) into shape (5,3)
> df.groupby('A').transform(lambda x: (x['C'] - x['D']).mean())
TypeError: cannot concatenate a non-NDFrame object
どうして? ドキュメントの例は、transform
グループを呼び出すと行ごとの演算処理ができることを示唆しているようです:
# Note that the following suggests row-wise operation (x.mean is the column mean)
zscore = lambda x: (x - x.mean()) / x.std()
transformed = ts.groupby(key).transform(zscore)
つまり、変換は本質的に特定のタイプの適用(集約されないもの)だと思いました。どこが間違っているのですか?
参考までに、上記の元のデータフレームの構成を以下に示します。
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C' : randn(8), 'D' : randn(8)})
zscore
)コピーしたドキュメントの例を見ると、transform
それぞれx
が内のアイテムであると想定し、グループ内のアイテムごとにgroup
値を返すラムダ関数を受け取ります。何が欠けていますか?
apply
df全体transform
を渡しますが、各列をシリーズとして個別に渡します。2)apply
任意の形状出力(スカラー/シリーズ/データフレーム/配列/リスト... )を返すことができますがtransform
、グループと同じ長さのシーケンス(1Dシリーズ/配列/リスト)を返す必要があります。OPが必要であるのはこのためですapply()
ませんtransform()
。このドキュメントは両方の違いを明確に説明していないため、これは良い質問です。(apply/map/applymap
、または他のものとの区別に似ています...)
transform
、数値、行、または引数と同じ形状を返す必要があります。数値の場合、その数値はグループ内のすべての要素に設定され、行の場合、グループ内のすべての行にブロードキャストされます。コードでは、lambda関数がグループにブロードキャストできない列を返します。