関心のある変数がBuy/Sell
であるトレーダートランザクションのデータセットがあります。これはバイナリであり、トランザクションが買いの場合は1、売りの場合は0の値を取ります。例は次のようになります。
Trader Buy/Sell
A 1
A 0
B 1
B 1
B 0
C 1
C 0
C 0
各トレーダーのネットBuy/Sell
を計算して、トレーダーが買いとして取引の50%を超える場合、50%未満の場合はBuy/Sell
が1になるようにします。購入すると、彼のBuy/Sell
は0になり、正確に50%の場合、NAになります(将来の計算では無視されます)。
したがって、トレーダーAの場合、購入比率は(購入数)/(トレーダーの総数)= 1/2 = 0.5であり、NAが得られます。
トレーダーBの場合、2/3 = 0.67であり、1が得られます。
トレーダーCの場合、1/3 = 0.33であり、0が得られます。
テーブルは次のようになります。
Trader Buy/Sell
A NA
B 1
C 0
最終的には、購入の合計数(この場合は1)と、取引の合計数(NAを除く)(この場合は2)を計算したいと思います。2番目の表には興味がありません。興味があるだけです。 Buy/Sell
の合計購入数と合計合計数(カウント)。
パンダでこれを行うにはどうすればよいですか?
import numpy as np
import pandas as pd
df = pd.DataFrame({'Buy/Sell': [1, 0, 1, 1, 0, 1, 0, 0],
'Trader': ['A', 'A', 'B', 'B', 'B', 'C', 'C', 'C']})
grouped = df.groupby(['Trader'])
result = grouped['Buy/Sell'].agg(['sum', 'count'])
means = grouped['Buy/Sell'].mean()
result['Buy/Sell'] = np.select(condlist=[means>0.5, means<0.5], choicelist=[1, 0],
default=np.nan)
print(result)
収量
Buy/Sell sum count
Trader
A NaN 1 2
B 1 2 3
C 0 1 3
私の元の回答では、カスタムアグリゲーターcategorize
を使用しました。
def categorize(x):
m = x.mean()
return 1 if m > 0.5 else 0 if m < 0.5 else np.nan
result = df.groupby(['Trader'])['Buy/Sell'].agg([categorize, 'sum', 'count'])
result = result.rename(columns={'categorize' : 'Buy/Sell'})
カスタム関数を呼び出すと便利な場合がありますが、カスタム関数を使用すると、組み込みのアグリゲーター(groupby/agg/mean
など)と比較してパフォーマンスが大幅に低下することがよくあります。組み込みのアグリゲーターはCythonizedですが、カスタム関数はパフォーマンスをプレーンなPython forループ速度に低下させます。
グループの数が多い場合、速度の違いは特に顕著です。たとえば、1000グループの10000行のDataFrameの場合、
import numpy as np
import pandas as pd
np.random.seed(2017)
N = 10000
df = pd.DataFrame({
'Buy/Sell': np.random.randint(2, size=N),
'Trader': np.random.randint(1000, size=N)})
def using_select(df):
grouped = df.groupby(['Trader'])
result = grouped['Buy/Sell'].agg(['sum', 'count'])
means = grouped['Buy/Sell'].mean()
result['Buy/Sell'] = np.select(condlist=[means>0.5, means<0.5], choicelist=[1, 0],
default=np.nan)
return result
def categorize(x):
m = x.mean()
return 1 if m > 0.5 else 0 if m < 0.5 else np.nan
def using_custom_function(df):
result = df.groupby(['Trader'])['Buy/Sell'].agg([categorize, 'sum', 'count'])
result = result.rename(columns={'categorize' : 'Buy/Sell'})
return result
using_select
はusing_custom_function
より50倍以上高速です。
In [69]: %timeit using_custom_function(df)
10 loops, best of 3: 132 ms per loop
In [70]: %timeit using_select(df)
100 loops, best of 3: 2.46 ms per loop
In [71]: 132/2.46
Out[71]: 53.65853658536585