Pandas DataFrame 合并两个值而不是匹配一个值

Pandas DataFrame merge between two values instead of matching one

我有一个带有日期列的数据框,我想将它与另一个数据框合并,但不匹配该列,但如果日期列介于第二个数据框的两列之间。

我相信我可以通过在第一个上使用 apply 来根据这些标准过滤第二个然后组合结果来实现这一点,但在实践中 apply 是一种非常缓慢的处理方式。

有没有办法将匹配合并为 BETWEEN 而不是完全匹配。

示例数据框:

,Code,Description,BeginDate,EndDate,RefSessionTypeId,OrganizationCalendarId
0,2014-2015,School Year: 2014-2015,2014-08-18 00:00:00.000,2015-08-01 00:00:00.000,1,3
1,2012-2013,School Year: 2012-2013,2012-09-01 00:00:00.000,2013-08-16 00:00:00.000,1,2
2,2013-2014,School Year: 2013-2014,2013-08-19 00:00:00.000,2014-08-17 00:00:00.000,1,1

不是在 date=BeginDate 或 date=EndDate 上合并,我想在日期 BETWEEN(BeginDate, EndDate)

上匹配

您可以使用numpy.searchsorted()来模拟BETWEEN

假设您的数据和查找值如下所示:

In [162]: data = pd.DataFrame({
   .....:     'Date': pd.Series(pd.np.random.randint(1429449000, 1429649000, 1000) * 1E9).astype('datetime64[ns]'),
   .....:     'Value': pd.np.random.randint(0, 100, 1000),
   .....: })

In [163]: data.head()
Out[163]:
                 Date  Value
0 2015-04-21 13:37:37     60
1 2015-04-20 06:27:43     76
2 2015-04-20 09:01:51     70
3 2015-04-21 10:47:31      5
4 2015-04-19 18:39:45     27

In [164]:

In [164]: lookup = pd.Series(
   .....:     pd.np.random.randint(0, 10, 5),
   .....:     index=pd.Series(pd.np.random.randint(1429449000, 1429649000, 5) * 1E9).astype('datetime64[ns]'),
   .....: )

In [165]: lookup
Out[165]:
2015-04-21 11:10:39    4
2015-04-21 07:07:51    1
2015-04-20 08:27:19    1
2015-04-21 09:58:42    6
2015-04-20 06:46:12    7
dtype: int32

您首先要确保 data['Date'] 中的所有日期都在 lookup 的索引中可用。然后,按日期对查找进行排序。

In [166]: lookup[data['Date'].max()] = lookup[data['Date'].min()] = None

In [167]: lookup = lookup.sort_index()

现在到了重要的一点——使用 NumPy 的非常快的searchsorted() 方法 来获取索引:

In [168]: indices = pd.np.searchsorted(lookup.index.astype(long), data['Date'].astype(long).values, side='left')

In [169]: data['Lookup'] = lookup.iloc[indices].values

In [170]: data.head()
Out[170]:
                 Date  Value Lookup
0 2015-04-21 13:37:37     60   None
1 2015-04-20 06:27:43     76      7
2 2015-04-20 09:01:51     70      1
3 2015-04-21 10:47:31      5      4
4 2015-04-19 18:39:45     27      7

编辑:您可能希望将数据集中的日期范围转换为单个系列,如上面的 lookup。这是因为在日期范围重叠的情况下,并不总是很清楚要查找哪个值。

我最终意识到我想多了,我在两个 table 中添加了一个名为 merge 的列,它全是 1

然后我可以对该列进行合并,并对合并后的结果进行常规布尔过滤器 table。

a["merge"] = 1
b["merge"] = 1
c = a.merge(b, on="merge")

然后过滤 c