首页 > 解决方案 > 基于重叠时间间隔连接两个数据集

问题描述

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

数据集 1

开始日期 结束日期 字段1
2020-01-01 2020-06-30 一个
2020-07-01 2020-12-31

数据集 2

开始日期 结束日期 字段2
2020-01-01 2020-04-30 D
2020-05-01 2020-08-31
2020-09-01 2020-12-31 F

组合数据集

开始日期 结束日期 字段1 字段2
2020-01-01 2020-04-30 一个 D
2020-05-01 2020-06-30 一个
2020-07-01 2020-08-31
2020-09-01 2020-12-31 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'])

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

标签: pythonpandasalgorithm

解决方案


您可以按以下步骤进行:

  1. 对于,通过对应于每行从 到 的期间来 定义每df1行的日期范围pd.date_range()start_dateend_date
  2. 同样,对于df2以类似方式定义每一行的日期范围
  3. 将新创建的日期列表date_range分解为多行df1df2每个日期在一行中。
  4. df1对每个数据帧中df2date_range列执行内部合并。现在,我们已经可以获取每个原始数据帧中公共日期的交集,以进行进一步处理。
  5. Group byfield1并且field2在交集日期上,我们可以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

推荐阅读