データ内のいくつかの変位値をマークしたいのですが、DataFrameの各行について、たとえば次のような新しい列にエントリを追加します。この値を保持する「xtile」。
たとえば、次のようなデータフレームを作成するとします。
import pandas, numpy as np
dfrm = pandas.DataFrame({'A':np.random.Rand(100),
'B':(50+np.random.randn(100)),
'C':np.random.randint(low=0, high=3, size=(100,))})
そして、配列内の各要素の五分位数を計算するための独自の関数を作成するとします。これには独自の関数がありますが、たとえばscipy.stats.mstats.mquantileを参照するだけです。
import scipy.stats as st
def mark_quintiles(x, breakpoints):
# Assume this is filled in, using st.mstats.mquantiles.
# This returns an array the same shape as x, with an integer for which
# breakpoint-bucket that entry of x falls into.
さて、本当の問題は、transform
を使用してデータに新しい列を追加する方法です。このようなもの:
def transformXtiles(dataFrame, inputColumnName, newColumnName, breaks):
dataFrame[newColumnName] = mark_quintiles(dataFrame[inputColumnName].values,
breaks)
return dataFrame
その後:
dfrm.groupby("C").transform(lambda x: transformXtiles(x, "A", "A_xtile", [0.2, 0.4, 0.6, 0.8, 1.0]))
問題は、上記のコードが新しい列「A_xtile」を追加しないことです。データフレームを変更せずに返すだけです。 NaNのように "A_xtile"と呼ばれるダミー値でいっぱいの列を最初に追加した場合、doesはこの列を正常に上書きして、正しい五分位のマーキングを含めます。
ただし、このようなものをすぐに追加したい場合は、最初に列に書き込む必要があるので非常に不便です。
単純なapply
は、グループごとにサイズが異なる可能性のある結果の配列を理解する方法がわからないため、ここでは機能しません。
apply
でどのような問題が発生していますか?これはこのおもちゃの例で機能し、グループの長さは異なります。
In [82]: df
Out[82]:
X Y
0 0 -0.631214
1 0 0.783142
2 0 0.526045
3 1 -1.750058
4 1 1.163868
5 1 1.625538
6 1 0.076105
7 2 0.183492
8 2 0.541400
9 2 -0.672809
In [83]: def func(x):
....: x['NewCol'] = np.nan
....: return x
....:
In [84]: df.groupby('X').apply(func)
Out[84]:
X Y NewCol
0 0 -0.631214 NaN
1 0 0.783142 NaN
2 0 0.526045 NaN
3 1 -1.750058 NaN
4 1 1.163868 NaN
5 1 1.625538 NaN
6 1 0.076105 NaN
7 2 0.183492 NaN
8 2 0.541400 NaN
9 2 -0.672809 NaN