Python Pandas - 矢量化自定义函数而不是apply

时间:2017-03-16 15:01:20

标签: python pandas vectorization

我有一个pandas DataFrame,其城市名称和日期如下:

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

我还有另一个DataFrame在一个给定的时间范围内将一个人与城市匹配(它基本上说这个人在这个城市的开始日期和结束日期之间)

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逐行应用于df.apply(lambda x: myfunc(x['CITY'], x['DATE']), axis=1)

myfunc只需在db中标识正确的PERSON,如下所示:

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

这很好但是对于非常大的数据帧来说相当慢...我试图以某种方式将db数据合并到df或者至少实现我所做的矢量化版本依赖于逐行实现。 有帮助吗?

1 个答案:

答案 0 :(得分: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'个条目与您提供的数据相匹配。