使用开始和结束日期验证数据框重复项
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_Date 和 Element_End_Date 都是 datetime
类型(不是字符串)。
- PERSON_NUMBER 是 index 列,如您的样本所示。
完成任务的准备步骤是定义一个函数来获取行
每组行的重叠日期范围:
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
我有以下员工数据框,由“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_Date 和 Element_End_Date 都是 datetime 类型(不是字符串)。
- PERSON_NUMBER 是 index 列,如您的样本所示。
完成任务的准备步骤是定义一个函数来获取行 每组行的重叠日期范围:
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