2017-03-16 46 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 

我想将列添加到df,以确定这是人在给定的城市为给定的每一行日期。

我能够使用自定义函数myfunc实现它,我使用df.apply(lambda x: myfunc(x['CITY'], x['DATE']), axis=1)将行应用到df

myfunc简单地识别db正确PERSON如下:

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

这种运作良好,但它是非常大的dataframes相当缓慢......我试图在db数据以某种方式合并到df或至少在不依赖行方式实现的情况下实现我所做的矢量化版本。 有什么帮助吗?

回答

3

使用pd.merge_asof

  • df必须'DATE'
  • db进行排序必须由'START'然后进行排序由'END'
  • 我们使用by参数只能由'CITY'
  • query在匹配结束以确保我们只得到'END' >= 'DATE'

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 

注意,只有'PARIS'条目与您所提供的数据进行匹配。