2017-03-16 10 views
1

を適用し、次のように私は都市の名前と日付を持つパンダのデータフレームを持っている: Pythonのパンダ - ベクトル化のカスタム関数の代わりに、

In[34]: df.head(6) 
Out[34]: 
     CITY  DATE 
0 LONDON 2017-03-12 
1 LONDON 2017-03-12 
2  PARIS 2014-05-05 
3  PARIS 2017-03-12 
4 LONDON 2017-03-12 
5 NEW-YORK 2017-03-12 

私はまた、別のデータフレームは、与えられた時間範囲のために街に人をマッチングしています

In[51]: db.head() 
Out[51]: 
     CITY PERSON  START   END 
0  PARIS ID4 2014-01-01 2017-03-16 
1 NEW-YORK ID5 2014-01-07 2016-12-31 
2 LONDON ID1 2014-01-01 2016-05-08 
3 MONTREAL ID1 2016-05-09 2017-03-16 
4  TOKYO ID5 2017-01-01 2017-03-16 

Iは、所与の都市者が与えられたためであった行ごとに決定するdfに列を追加したい(それは基本的に、この人は、開始日と終了日との間のこの都市であったと言います)日付。

df.apply(lambda x: myfunc(x['CITY'], x['DATE']), axis=1)を使用してdfに行方向に適用するカスタム関数myfuncを使用してこれを実現できました。次のように

myfuncは単にdb正しいPERSONに識別します。

def myfunc(city, date): 
    return db.loc[(db.CITY==city) & (db.START <= date) & (db.END >= date), 'PERSON'].values[0] 

これはうまく動作しますが、それは非常に大規模なデータフレームのためにかなり遅いです...私は何とかdfにまたはでdbデータをマージしようとしていました行ごとの実装に頼ることなく、私が行ったことのベクトル化されたバージョンを実装することは、少なくとも可能です。 助けてください?

答えて

3

使用pd.merge_asof

  • df我々だけで'CITY'
  • queryで一致しbyパラメータを使用'END'
  • によって、その後'START'によってソートする必要があります'DATE'
  • dbによってソートされなければなりません終了することを確実にするために終了'END' >= 'DATE'

のみ 'PARIS'エントリは、あなたが提供されたデータと一致している
pd.merge_asof(
    df.sort_values('DATE'), 
    db.sort_values(['START', 'END']), 
    left_on='DATE', right_on='START', by='CITY' 
).query('DATE <= END') 

    CITY  DATE PERSON  START  END 
0 PARIS 2014-05-05 ID4 2014-01-01 2017-03-16 
3 PARIS 2017-03-12 ID4 2014-01-01 2017-03-16 

注意してください。

関連する問題