2017-11-29 11 views
-1

私は次の形式でパンダのデータフレームを持っている:Pythonのパンダ:ベクター化時系列ウィンドウ関数

'customer_id','transaction_dt','product','price','units' 
1,2004-01-02,thing1,25,47 
1,2004-01-17,thing2,150,8 
2,2004-01-29,thing2,150,25 
3,2017-07-15,thing3,55,17 
3,2016-05-12,thing3,55,47 
4,2012-02-23,thing2,150,22 
4,2009-10-10,thing1,25,12 
4,2014-04-04,thing2,150,2 
5,2008-07-09,thing2,150,43 

私は30日の窓を示す2つの新しいフィールドを作成するには、次のように書かれている:

import numpy as np 
import pandas as pd 

start_date_period = pd.period_range('2004-01-01', '12-31-2017', freq='30D') 
end_date_period = pd.period_range('2004-01-30', '12-31-2017', freq='30D') 

def find_window_start_date(x): 
    window_start_date_idx = np.argmax(x < start_date_period.end_time) 
    return start_date_period[window_start_date_idx] 

df['window_start_dt'] = df['transaction_dt'].apply(find_window_start_date) 

def find_window_end_date(x): 
    window_end_date_idx = np.argmin(x > end_date_period.start_time) 
    return end_date_period[window_end_date_idx] 

df['window_end_dt'] = df['transaction_dt'].apply(find_window_end_date) 

を残念ながら、これは私のアプリケーションに行単位で適用するには遅すぎます。可能であれば、これらの機能をベクトル化するためのヒントをお待ちしております。

EDIT:

結果のデータフレームは、このレイアウトを持っている必要があります。

'customer_id','transaction_dt','product','price','units','window_start_dt','window_end_dt' 

それは正式な意味でのリサンプリングやウィンドウ表示する必要はありません。追加される 'window_start_dt'と 'window_end_dt'カラムが必要です。現在のコードは機能しますが、可能であればベクター化する必要があります。

+0

確認するには、その30日間のウィンドウに属する最後の日付(データに表示されている日付)を抽出するだけですか? –

+0

@AntoineZambelli私はあなたが何を意味していると思う。私は実際にはgroupby操作を行う必要はありませんので、Windowsの最初/最後の日付を選択する必要はありません。既存の行に適用するだけです。私が誤解すれば謝罪します。 – Pylander

+0

さて、うまくいけば、私はそれを正しく理解しています、あなたは 'resample'を望んでいると思います! –

答えて

0

EDIT 2pandas.cutがビルトインされています

tt=[[1,'2004-01-02',0.1,25,47], 
[1,'2004-01-17',0.2,150,8], 
[2,'2004-01-29',0.2,150,25], 
[3,'2017-07-15',0.3,55,17], 
[3,'2016-05-12',0.3,55,47], 
[4,'2012-02-23',0.2,150,22], 
[4,'2009-10-10',0.1,25,12], 
[4,'2014-04-04',0.2,150,2], 
[5,'2008-07-09',0.2,150,43]] 



start_date_period = pd.date_range('2004-01-01', '12-01-2017', freq='MS') 
end_date_period = pd.date_range('2004-01-30', '12-31-2017', freq='M') 

df = pd.DataFrame(tt,columns=['customer_id','transaction_dt','product','price','units']) 
df['transaction_dt'] = pd.Series([pd.to_datetime(sub_t[1],format='%Y-%m-%d') for sub_t in tt]) 

the_cut = pd.cut(df['transaction_dt'],bins=start_date_period,right=True,labels=False,include_lowest=True) 

df['win_start_test'] = pd.Series([start_date_period[int(x)] if not np.isnan(x) else 0 for x in the_cut]) 
df['win_end_test'] = pd.Series([end_date_period[int(x)] if not np.isnan(x) else 0 for x in the_cut]) 

print(df.head()) 

win_start_testwin_end_testは彼らのカウンターパートと同じである必要があり、あなたの関数を使用して計算。

ValueErrorは、該当する行のx~intには出ていませんでした。私はNaN小切手を追加しましたが、このおもちゃの例では必要ありませんでした。

pd.date_rangeへの変更とし、月末フラグスタートヶ月のMMSの使用だけでなく、datetimeに日付文字列を変換します。

+0

ありがとうございますが、私はこれが私がしたいとは思わない。私はカレンダーの日付にリンクされていない、私が定義した任意のウィンドウを使用できるようにしたいと思います。これらのウィンドウが互いに連続しているという保証もありません。 – Pylander

+0

任意のウィンドウがカレンダーの日付にリンクされていない場合、私は本当に混乱しています。私は、 'resample'は連続していないデータ(単にソートする必要がある)で動作すると思います。たぶんあなたは「ローリング」したい? –

+0

いくつかの説明を追加しました。 groupby型の計算を開始する前に、結果データを他のデータソースと結合する必要があります。そのため、適用されたウィンドウの日付だけが必要です。私が再サンプリング/ローリングすると、変換/集計を時期尚早にやっているだろう。 – Pylander