【问题标题】:Pandas DataFrame merge between two values instead of matching onePandas DataFrame 在两个值之间合并而不是匹配一个
【发布时间】:2015-04-22 15:21:02
【问题描述】:

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

我相信我可以通过在第一个上使用 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

我希望在日期 BETWEEN(BeginDate, EndDate) 上匹配,而不是在 date=BeginDate 或 date=EndDate 上进行合并

【问题讨论】:

  • 你能添加几行数据和预期的输出吗?

标签: python pandas merge between


【解决方案1】:

您可以使用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。这是因为在日期范围重叠的情况下,并不总是很清楚要查找哪个值。

【讨论】:

    【解决方案2】:

    我最终意识到我想多了

    然后我可以在该列上进行合并,并对生成的合并表执行常规布尔过滤器。

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

    然后在 c 上过滤

    【讨论】:

      猜你喜欢
      • 2023-03-24
      • 2021-03-13
      • 1970-01-01
      • 2019-02-28
      • 2018-05-22
      • 1970-01-01
      • 2017-12-23
      • 2021-08-15
      • 1970-01-01
      相关资源
      最近更新 更多