2013-03-07 5 views
9

は、私がデータフレームがあるとパンダ:グループオブジェクトに異なるアイテムに異なる機能を適用します:Pythonは、次のように

In [1]: test_dup_df 

Out[1]: 
        exe_price exe_vol flag 
2008-03-13 14:41:07 84.5 200  yes 
2008-03-13 14:41:37 85.0 10000 yes 
2008-03-13 14:41:38 84.5 69700 yes 
2008-03-13 14:41:39 84.5 1200 yes 
2008-03-13 14:42:00 84.5 1000 yes 
2008-03-13 14:42:08 84.5 300  yes 
2008-03-13 14:42:10 84.5 88100 yes 
2008-03-13 14:42:10 84.5 11900 yes 
2008-03-13 14:42:15 84.5 5000 yes 
2008-03-13 14:42:16 84.5 3200 yes 

は私がグループに時間14:42:10で重複データを欲しいとexe_priceexe_volに異なる機能を適用します(例: exe_volを合計し、exe_priceという計算量加重平均を計算します)。私はグループに重複したインデックスを

In [2]: grouped = test_dup_df.groupby(level=0) 

を行い、その後、最初または最後の行のいずれかを取得するためにfirst()またはlast()機能を使用しますが、これは私が欲しいものは本当にないことを知っています。

異なる列の値にグループ化して別の(私が書いた)関数を適用する方法はありますか?あなたができるnumpyのひどくpandasに精通し、しかし純粋でない

+0

これは私に2つの別々のデータフレームを与えることはないでしょうか?私はそれをgrouped.first()またはgrouped.last()の出力に似ている1つのデータフレームに入れたいと思います。私は何かが不足しているかもしれない? – kunitomo

答えて

1

:それは非常に明確で読みやすいので

tot_vol = np.sum(grouped['exe_vol']) 
avg_price = np.average(grouped['exe_price'], weights=grouped['exe_vol']) 
+0

迅速な対応をありがとうございます。私は私の 'グループ化された'が今ではパンダのDataFrameGroupByオブジェクトなので、本当にあなたの身体を直接適用できないのだろうか? – kunitomo

+0

おそらく、別のデータフレームにすることができます[ここ](http://stackoverflow.com/questions/10373660/converting-a-pandas-groupby-object-to-dataframe) – askewchan

+0

私は参照してください。どうもありがとうございました。 – kunitomo

4

私は、@ waitingkuoの答えが好きです。

とにかく、これは速くて見えるので、私はこれを保っています。少なくとも、Pandasバージョン0.10.0ではそうです。状況がmay (hopefully) change in the futureなので、特に異なるバージョンのPandasを使用している場合は、ベンチマークを再実行してください。のはtimeitベンチマークと

import pandas as pd 
import io 
import timeit 

data = '''\ 
date time  exe_price exe_vol flag 
2008-03-13 14:41:07 84.5 200  yes 
2008-03-13 14:41:37 85.0 10000 yes 
2008-03-13 14:41:38 84.5 69700 yes 
2008-03-13 14:41:39 84.5 1200 yes 
2008-03-13 14:42:00 84.5 1000 yes 
2008-03-13 14:42:08 84.5 300  yes 
2008-03-13 14:42:10 10 88100 yes 
2008-03-13 14:42:10 100 11900 yes 
2008-03-13 14:42:15 84.5 5000 yes 
2008-03-13 14:42:16 84.5 3200 yes''' 

df = pd.read_table(io.BytesIO(data), sep='\s+', parse_dates=[[0, 1]], 
        index_col=0) 


def func(subf): 
    exe_vol = subf['exe_vol'].sum() 
    exe_price = ((subf['exe_price']*subf['exe_vol']).sum() 
       /exe_vol) 
    flag = True 
    return pd.Series([exe_price, exe_vol, flag], 
        index=['exe_price', 'exe_vol', 'flag']) 
    # return exe_price 

def using_apply(): 
    return df.groupby(df.index).apply(func) 

def using_helper_column(): 
    df['weight'] = df['exe_price'] * df['exe_vol'] 
    grouped = df.groupby(level=0, group_keys=True) 
    result = grouped.agg({'weight': 'sum', 'exe_vol': 'sum'}) 
    result['exe_price'] = result['weight']/result['exe_vol'] 
    result['flag'] = True 
    result = result.drop(['weight'], axis=1) 
    return result 

result = using_apply() 
print(result) 
result = using_helper_column() 
print(result) 

time_apply = timeit.timeit('m.using_apply()', 
         'import __main__ as m ', 
         number=1000) 
time_helper = timeit.timeit('m.using_helper_column()', 
         'import __main__ as m ', 
         number=1000) 
print('using_apply: {t}'.format(t = time_apply)) 
print('using_helper_column: {t}'.format(t = time_helper)) 

利回り

     exe_vol exe_price flag 
date_time          
2008-03-13 14:41:07  200  84.50 True 
2008-03-13 14:41:37 10000  85.00 True 
2008-03-13 14:41:38 69700  84.50 True 
2008-03-13 14:41:39  1200  84.50 True 
2008-03-13 14:42:00  1000  84.50 True 
2008-03-13 14:42:08  300  84.50 True 
2008-03-13 14:42:10 100000  20.71 True 
2008-03-13 14:42:15  5000  84.50 True 
2008-03-13 14:42:16  3200  84.50 True 

using_apply: 3.0081038475 
using_helper_column: 1.35300707817 
+0

ありがとうございます! PS:うまくいけば、私は2百万以上の行を持っているので、新しいデータフレームを作成することはあまりメモリを必要としません... – kunitomo

+0

@kunitomo:私は間違っているようです - waitingkuoは複数の列に集約する方法を示します。 – unutbu

+0

これは、パンダ0.18とPython 3.4.5の2倍の速さです。 – naught101

12

は独自の関数を適用します。

In [12]: def func(x): 
      exe_price = (x['exe_price']*x['exe_vol']).sum()/x['exe_vol'].sum() 
      exe_vol = x['exe_vol'].sum() 
      flag = True   
      return Series([exe_price, exe_vol, flag], index=['exe_price', 'exe_vol', 'flag']) 


In [13]: test_dup_df.groupby(test_dup_df.index).apply(func) 
Out[13]: 
        exe_price exe_vol flag 
date_time         
2008-03-13 14:41:07  84.5  200 True 
2008-03-13 14:41:37  85 10000 True 
2008-03-13 14:41:38  84.5 69700 True 
2008-03-13 14:41:39  84.5 1200 True 
2008-03-13 14:42:00  84.5 1000 True 
2008-03-13 14:42:08  84.5  300 True 
2008-03-13 14:42:10  20.71 100000 True 
2008-03-13 14:42:15  84.5 5000 True 
2008-03-13 14:42:16  84.5 3200 True 
+0

これは素晴らしいことです! 'flag = True'の目的は何ですか? – unutbu

+0

この関数は、元の列と同じ列をすべて含むSeriesを返します。私はどの旗が意味するのか分からないので、単に真を返す。 – waitingkuo

+0

ああ、私の愚かなこと。とにかく、この答えに感謝します。 – unutbu

関連する問題