使用开始和结束日期验证数据框重复项

Validate dataframe duplicates using start and end date

我有以下员工数据框,由“PERSON_NUMBER”表示,他们在“ELEMENT_NAME”中享有的福利以及有效时间:

                       ELEMENT_NAME Element_Start_Date Element_End_Date
PERSON_NUMBER                                                          
3720081000         Standard Bonus M         2017-09-30       2025-12-31
3720081000            IE Healthcare         2016-12-01       2025-12-31
3720081000              IE Pensions         2016-09-01       2019-12-31
3720081000              IE Pensions         2019-09-01       2025-12-31
3720081000              IE Pensions         2020-03-01       2025-12-31
3720082294         IE Car Allowance         2020-03-09       2025-12-31
3720082295         Standard Bonus K         2020-03-23       2025-12-31
3720082305              IE Pensions         2020-05-25       2025-12-31
3720082305              IE Pensions         2017-05-25       2019-12-31
3720082395         Standard Bonus J         2020-03-23       2020-04-31
3720082395         Standard Bonus J         2020-05-25       2020-12-31
3720082395         Standard Bonus J         2020-09-25       2025-12-31

一个人的记录中可以有超过 1 个元素,但对于每个唯一元素,我们不能在任何时间点重复该元素。

案例 1:

因此,例如,在此数据框中,员工 3720081000 有 2 个第一笔奖金,但对于“IE 养老金”,您可以看到它第一次收到“IE 养老金”时,结束日期是“2019- 12-31”,但下一行有相同的元素,从“2019-09-01”开始,意思是从“2019 年 9 月到 12 月”,这个元素在他的记录中出现了两次。然后,此元素再次出现在第 3 条记录中。

案例 2:

但是例如员工 3720082305 就可以了,因为虽然他们有两次“IE 养老金”,但开始日期和结束日期不会冲突。

案例 3:

对于员工3720082295你可以看到他们有3条“Standard Bonus J”的记录。第一条和第二条记录是可以的,因为福利从 Match 开始到 4 月,然后另一个记录从 5 月底开始,到 2025 年结束。但是,第三条记录是在 2020 年 9 月到 2025 年创建的,并且与之前的记录冲突,因为此人已打开此福利。

我希望得到所有相互冲突的行。

因此,此数据的预期输出将是:

                       ELEMENT_NAME Element_Start_Date Element_End_Date
PERSON_NUMBER                                                          
3720081000              IE Pensions         2016-09-01       2019-12-31
3720081000              IE Pensions         2019-09-01       2025-12-31
3720081000              IE Pensions         2020-03-01       2025-12-31
3720082395         Standard Bonus J         2020-05-25       2020-12-31
3720082395         Standard Bonus J         2020-09-25       2025-12-31

因此,如果员工编号在他们拥有的任何元素中存在任何错误,我想 return 通过“人员编号”

该元素的所有行

构建此验证的最佳方法是什么?

让我们从样本数据中的一个小修正开始:其中一个值 在 Element_End_Date 中是 2020-04-31,这不是任何有效日期 (4月只有30天),所以我改成了2020-04-30.

我还假设:

  • Element_Start_DateElement_End_Date 都是 datetime 类型(不是字符串)。
  • PERSON_NUMBERindex 列,如您的样本所示。

完成任务的准备步骤是定义一个函数来获取行 每组行的重叠日期范围:

def getOverlapping(grp):
    ind = pd.IntervalIndex.from_arrays(grp.Element_Start_Date, grp.Element_End_Date)
    ovl = [ind.overlaps(x).sum() > 1 for x in ind]
    return grp[ovl]

要获得结果,请应用它:

df.set_index('ELEMENT_NAME', append=True).groupby(level=[0,1])\
    .apply(getOverlapping).reset_index(level=[2, 3], drop=True).reset_index(level=1)

结果是:

                   ELEMENT_NAME Element_Start_Date Element_End_Date
PERSON_NUMBER                                                      
3720081000          IE Pensions         2016-09-01       2019-12-31
3720081000          IE Pensions         2019-09-01       2025-12-31
3720081000          IE Pensions         2020-03-01       2025-12-31
3720082395     Standard Bonus J         2020-05-25       2020-12-31
3720082395     Standard Bonus J         2020-09-25       2025-12-31