【问题标题】:Joining two datasets based on overlapping time intervals基于重叠时间间隔连接两个数据集
【发布时间】:2021-05-01 02:02:41
【问题描述】:

我正在尝试根据重叠间隔“合并”两个 Dataframe,如下所示:

数据集 1

start_date end_date field1
2020-01-01 2020-06-30 A
2020-07-01 2020-12-31 B

数据集 2

start_date end_date field2
2020-01-01 2020-04-30 D
2020-05-01 2020-08-31 E
2020-09-01 2020-12-31 F

组合数据集

start_date end_date field1 field2
2020-01-01 2020-04-30 A D
2020-05-01 2020-06-30 A E
2020-07-01 2020-08-31 B E
2020-09-01 2020-12-31 B F

代码是python,示例如下

import pandas as pd
df1 = pd.DataFrame([['2020-01-01','2020-06-30','A'],
                    ['2020-07-01','2020-12-31','B']], 
                     columns = ['start_date', 'end_date', 'field1'])

df2 = pd.DataFrame([['2020-01-01','2020-04-30','D'],
                    ['2020-05-01','2020-08-31','E'],
                    ['2020-09-01','2020-12-31','F']], 
                     columns = ['start_date', 'end_date', 'field2'])


expected_output = pd.DataFrame([['2020-01-01','2020-04-30','A','D'],
                                ['2020-05-01','2020-06-30','A','E'],
                                ['2020-07-01','2020-08-31','B','E'],
                                ['2020-09-01','2020-12-31','B','F']], 
                                columns = ['start_date', 'end_date','field1', 'field2'])

我真的尝试过想办法做到这一点,但我必须说我的页面是空白的......非常感谢您的任何建议!

【问题讨论】:

  • @Andreas 感谢您的分享,但这是一个稍微不同的问题。
  • @Cambyst 您可以做的是将 df1 中的每个日期范围(开始-结束)与 df2 中的每个日期范围进行比较,并找到相交的日期范围(记住 field1 和 field2 的值)。每个非空交集都成为 expected_output 中的一行。我现在没有时间为此创建一个真正的答案。但也许这可以为您或其他人指明正确的方向。
  • @jch 我的解决方案与您的想法相同。在您发表评论时,我正在对代码进行最后的美化。

标签: python pandas algorithm


【解决方案1】:

您可以按以下步骤操作:

  1. 对于df1,通过pd.date_range() 定义每行的日期范围,对应于每行从start_dateend_date 的时间段
  2. 同样,df2 以类似方式定义每一行的日期范围
  3. df1df2 的每个新创建的date_range 中的日期列表分解为多行,每个日期在一行中。
  4. 在每个数据帧中的date_range 列上对df1df2 执行内部合并。现在,我们已经可以得到每个原始数据帧中公共日期的交集,以便进一步处理。
  5. 在交集日期按field1field2分组,取组中的第一个条目即可得到共同日期范围的新start_date
  6. 同样,我们可以通过获取组中的最后一个条目来获取公共日期范围的新end_date
  7. 最后,我们汇总条目并只取每个组中已经包含我们想要的所有必需信息的第一行。

df1a = (df1.assign(date_range=df1.apply(lambda x: pd.date_range(start=x['start_date'], end=x['end_date']), axis=1))
           .explode('date_range'))
df2a = (df2.assign(date_range=df2.apply(lambda x: pd.date_range(start=x['start_date'], end=x['end_date']), axis=1))
           .explode('date_range'))
df3 = df1a.merge(df2a, on='date_range')
df3['start_date'] = df3.groupby(['field1', 'field2'])['date_range'].transform('first')
df3['end_date'] = df3.groupby(['field1', 'field2'])['date_range'].transform('last')
df4 = df3.groupby(['field1', 'field2']).agg('first').reset_index()[['start_date', 'end_date', 'field1', 'field2']]



print(df4)

  start_date   end_date field1 field2
0 2020-01-01 2020-04-30      A      D
1 2020-05-01 2020-06-30      A      E
2 2020-07-01 2020-08-31      B      E
3 2020-09-01 2020-12-31      B      F

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-15
    • 2019-09-21
    • 1970-01-01
    • 2018-08-28
    相关资源
    最近更新 更多