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
我有一个带有日期列的数据框,我想将它与另一个数据框合并,但不匹配该列,但如果日期列介于第二个数据框的两列之间。
我相信我可以通过在第一个上使用 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