Pandas:删除出现在时间间隔 pandas 内的重复项
Pandas: Drop duplicates that appear within a time interval pandas
我们有一个包含 'ID' 和 'DAY' 列的数据框,显示特定客户何时提出投诉。我们需要从 'ID' 列中删除重复项,但前提是重复项相隔 30 天。请看下面的例子:
当前数据集:
ID DAY
0 1 22.03.2020
1 1 18.04.2020
2 2 10.05.2020
3 2 13.01.2020
4 3 30.03.2020
5 3 31.03.2020
6 3 24.02.2021
目标:
ID DAY
0 1 22.03.2020
1 2 10.05.2020
2 2 13.01.2020
3 3 30.03.2020
4 3 24.02.2021
有什么建议吗?我试过 groupby 然后创建一个循环来计算每个组合之间的差异,但是因为数据框有数百万行这将永远...
您可以尝试按 ID
列和 diff
每个组中的 DAY
列进行分组
df['DAY'] = pd.to_datetime(df['DAY'], dayfirst=True)
from datetime import timedelta
m = timedelta(days=30)
out = df.groupby('ID').apply(lambda group: group[~group['DAY'].diff().abs().le(m)]).reset_index(drop=True)
print(out)
ID DAY
0 1 2020-03-22
1 2 2020-05-10
2 2 2020-01-13
3 3 2020-03-30
4 3 2021-02-24
要转换为原始日期格式,您可以使用dt.strftime
out['DAY'] = out['DAY'].dt.strftime('%d.%m.%Y')
print(out)
ID DAY
0 1 22.03.2020
1 2 10.05.2020
2 2 13.01.2020
3 3 30.03.2020
4 3 24.02.2021
您可以计算每组连续日期之间的差异,并使用它来形成一个掩码以删除间隔少于 30 天的日期:
df['DAY'] = pd.to_datetime(df['DAY'], dayfirst=True)
mask = (df
.sort_values(by=['ID', 'DAY'])
.groupby('ID')['DAY']
.diff().lt('30d')
.sort_index()
)
df[~mask]
注意。这种方法的潜在缺点是,如果客户在 30 天内提出新的投诉,这将重新启动下一次投诉的阈值
输出:
ID DAY
0 1 2020-03-22
2 2 2020-10-05
3 2 2020-01-13
4 3 2020-03-30
6 3 2021-02-24
因此,另一种方法可能是 resample
每组数据到 30 天:
(df
.groupby('ID')
.resample('30d', on='DAY').first()
.dropna()
.convert_dtypes()
.reset_index(drop=True)
)
输出:
ID DAY
0 1 2020-03-22
1 2 2020-01-13
2 2 2020-10-05
3 3 2020-03-30
4 3 2021-02-24
我们有一个包含 'ID' 和 'DAY' 列的数据框,显示特定客户何时提出投诉。我们需要从 'ID' 列中删除重复项,但前提是重复项相隔 30 天。请看下面的例子:
当前数据集:
ID DAY
0 1 22.03.2020
1 1 18.04.2020
2 2 10.05.2020
3 2 13.01.2020
4 3 30.03.2020
5 3 31.03.2020
6 3 24.02.2021
目标:
ID DAY
0 1 22.03.2020
1 2 10.05.2020
2 2 13.01.2020
3 3 30.03.2020
4 3 24.02.2021
有什么建议吗?我试过 groupby 然后创建一个循环来计算每个组合之间的差异,但是因为数据框有数百万行这将永远...
您可以尝试按 ID
列和 diff
每个组中的 DAY
列进行分组
df['DAY'] = pd.to_datetime(df['DAY'], dayfirst=True)
from datetime import timedelta
m = timedelta(days=30)
out = df.groupby('ID').apply(lambda group: group[~group['DAY'].diff().abs().le(m)]).reset_index(drop=True)
print(out)
ID DAY
0 1 2020-03-22
1 2 2020-05-10
2 2 2020-01-13
3 3 2020-03-30
4 3 2021-02-24
要转换为原始日期格式,您可以使用dt.strftime
out['DAY'] = out['DAY'].dt.strftime('%d.%m.%Y')
print(out)
ID DAY
0 1 22.03.2020
1 2 10.05.2020
2 2 13.01.2020
3 3 30.03.2020
4 3 24.02.2021
您可以计算每组连续日期之间的差异,并使用它来形成一个掩码以删除间隔少于 30 天的日期:
df['DAY'] = pd.to_datetime(df['DAY'], dayfirst=True)
mask = (df
.sort_values(by=['ID', 'DAY'])
.groupby('ID')['DAY']
.diff().lt('30d')
.sort_index()
)
df[~mask]
注意。这种方法的潜在缺点是,如果客户在 30 天内提出新的投诉,这将重新启动下一次投诉的阈值
输出:
ID DAY
0 1 2020-03-22
2 2 2020-10-05
3 2 2020-01-13
4 3 2020-03-30
6 3 2021-02-24
因此,另一种方法可能是 resample
每组数据到 30 天:
(df
.groupby('ID')
.resample('30d', on='DAY').first()
.dropna()
.convert_dtypes()
.reset_index(drop=True)
)
输出:
ID DAY
0 1 2020-03-22
1 2 2020-01-13
2 2 2020-10-05
3 3 2020-03-30
4 3 2021-02-24