Pandas按客户分组计算日期与上一不同日期的天数差
Pandas 分组计算日期间隔(跳过同日期重复值)
需求说明
- 按
customerId维度分组,计算每行fromDate与该客户上一个不同的更早日期的天数差 - 每个客户最早的无历史数据的日期,对应差值为
None/NaT - 同日期存在多条重复记录时,所有记录都要回溯到上一个不同的更早日期计算差值,不能取紧邻同日期记录算0天差
原有代码问题
原实现直接对排序后的分组数据做shift()取相邻上一行值,未跳过相同日期的重复行,导致同日期的第二条及后续记录计算得到0天差,不符合预期。
原有错误实现代码
import pandas as pd d = {'customerId': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], 'fromDate': ['2021-02-22','2021-02-22', '2021-03-18','2021-03-18', '2021-03-18', '2021-03-22', '2021-02-10', '2021-09-07', None, '2022-01-18', '2021-05-17'], 'otherInformation': ['Cat', 'Dog', 'Elefant', 'Cat', 'Cat','Cat', 'Cat', 'Cat', 'Elefant', 'Fish', 'Fish'] } df = pd.DataFrame(data=d) print(df) df['fromDate'] = pd.to_datetime(df['fromDate'], errors='coerce') df['lastindays'] = df['fromDate'] - df.sort_values('fromDate').groupby('customerId')['fromDate'].shift() print(df)
正确实现方案
核心逻辑:先为每个客户的每个唯一日期匹配对应的上一个不同日期,再将匹配结果映射回所有同日期记录,避免同日期重复记录取到相邻同日期值。
import pandas as pd d = {'customerId': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2], 'fromDate': ['2021-02-22','2021-02-22', '2021-03-18','2021-03-18', '2021-03-18', '2021-03-22', '2021-02-10', '2021-09-07', None, '2022-01-18', '2021-05-17'], 'otherInformation': ['Cat', 'Dog', 'Elefant', 'Cat', 'Cat','Cat', 'Cat', 'Cat', 'Elefant', 'Fish', 'Fish'] } df = pd.DataFrame(data=d) # 转换日期格式,无效日期转NaT df['fromDate'] = pd.to_datetime(df['fromDate'], errors='coerce') # 提取每个客户的唯一日期序列,计算每个日期对应的上一个不同日期 unique_date_map = df[['customerId', 'fromDate']].drop_duplicates() unique_date_map['prev_date'] = unique_date_map.sort_values(['customerId', 'fromDate'])\ .groupby('customerId')['fromDate'].shift() # 将上一日期映射回原表,计算天数差 df = df.merge(unique_date_map, on=['customerId', 'fromDate'], how='left') df['lastindays'] = df['fromDate'] - df['prev_date'] print(df)
运行结果(符合预期)
customerId fromDate otherInformation prev_date lastindays 0 1 2021-02-22 Cat 2021-02-10 12 days 1 1 2021-02-22 Dog 2021-02-10 12 days 2 1 2021-03-18 Elefant 2021-02-22 24 days 3 1 2021-03-18 Cat 2021-02-22 24 days 4 1 2021-03-18 Cat 2021-02-22 24 days 5 1 2021-03-22 Cat 2021-03-18 4 days 6 1 2021-02-10 Cat NaT NaT 7 1 2021-09-07 Cat 2021-03-22 169 days 8 1 NaT Elefant NaT NaT 9 1 2022-01-18 Fish 2021-09-07 133 days 10 2 2021-05-17 Fish NaT NaT
内容的提问来源于stack exchange,提问作者Test
相关产品推荐
相关产品推荐

