按用户分组,基于d1列生成与d2列日期最接近的新列d3
问题描述
我有如下测试数据集:
import pandas as pd df = pd.DataFrame({'user':[1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,4], 'd1':['1995-09-01','1995-09-02','1995-10-03','1995-10-04','1995-10-05','1995-11-07','1995-11-08','1995-11-09','1995-11-10','1995-11-15','1995-12-18','1995-12-19','1995-12-20','1995-12-23','1995-12-26','1995-12-30'], 'd2':['1995-10-05','1995-10-05','1995-10-05', '1995-11-08','1995-11-08','1995-11-08','1995-11-08', '1995-12-10','1995-12-10','1995-12-10','1995-12-10', '1995-12-27','1995-12-27','1995-12-27','1995-12-27','1995-12-27'],})
按user和d1排序(df = df.sort_values(['user', 'd1']))后结果如下:
user d1 d2 1 1995-09-01 1995-10-05 1 1995-09-02 1995-10-05 1 1995-10-03 1995-10-05 2 1995-10-04 1995-11-08 2 1995-10-05 1995-11-08 2 1995-11-07 1995-11-08 2 1995-11-08 1995-11-08 3 1995-11-09 1995-12-10 3 1995-11-10 1995-12-10 3 1995-11-15 1995-12-10 3 1995-12-18 1995-12-10 4 1995-12-19 1995-12-27 4 1995-12-20 1995-12-27 4 1995-12-23 1995-12-27 4 1995-12-26 1995-12-27 4 1995-12-30 1995-12-27
需要生成新列d3,规则如下:
d3的值为当前user分组下,d1列中与d2列日期最接近的日期- 若
d2的日期存在于该分组的d1中,则d3直接取该日期 - 若不存在,则取该分组
d1中最接近d2的日期
期望得到如下DataFrame:
user d1 d2 d3 1 1995-09-01 1995-10-05 1995-10-03 1 1995-09-02 1995-10-05 1995-10-03 1 1995-10-03 1995-10-05 1995-10-03 2 1995-10-04 1995-11-08 1995-11-08 2 1995-10-05 1995-11-08 1995-11-08 2 1995-11-07 1995-11-08 1995-11-08 2 1995-11-08 1995-11-08 1995-11-08 3 1995-11-09 1995-12-10 1995-12-18 3 1995-11-10 1995-12-10 1995-12-18 3 1995-11-15 1995-12-10 1995-12-18 3 1995-12-18 1995-12-10 1995-12-18 4 1995-12-19 1995-12-27 1995-12-26 4 1995-12-20 1995-12-27 1995-12-26 4 1995-12-23 1995-12-27 1995-12-26 4 1995-12-26 1995-12-27 1995-12-26 4 1995-12-30 1995-12-27 1995-12-26
我参考过StackOverflow上的两个方案,但适配后未成功。
解决方案
步骤说明
- 将
d1和d2转换为日期类型,确保日期计算准确 - 按
user分组,对每个分组执行以下操作:- 获取当前分组的
d1日期数组 - 对分组内的
d2日期,先检查是否存在于d1中,存在则直接取值;不存在则计算日期差绝对值,找到最接近的日期
- 获取当前分组的
- 将结果合并回原DataFrame得到
d3列
代码实现
import pandas as pd import numpy as np # 1. 转换日期类型 df['d1'] = pd.to_datetime(df['d1']) df['d2'] = pd.to_datetime(df['d2']) # 2. 定义分组内找最接近日期的函数 def find_nearest_date(group): d1_dates = group['d1'].unique() d2_date = group['d2'].iloc[0] # 同一分组内d2日期相同 # 先检查d2是否在d1中 if d2_date in d1_dates: nearest = d2_date else: # 计算日期差的绝对值,找到最小差值对应的日期 diffs = np.abs(d1_dates - d2_date) nearest = d1_dates[np.argmin(diffs)] # 为分组内所有行赋值 group['d3'] = nearest return group # 3. 按user分组应用函数 df = df.groupby('user').apply(find_nearest_date) # 4. 转换回字符串格式(可选,根据需求调整) df['d1'] = df['d1'].dt.strftime('%Y-%m-%d') df['d2'] = df['d2'].dt.strftime('%Y-%m-%d') df['d3'] = df['d3'].dt.strftime('%Y-%m-%d') # 查看结果 print(df)
代码解释
- 日期转换:把字符串类型的日期转为
datetime类型,才能进行日期差值的数学计算 - 分组函数:同一用户的
d2日期完全一致,所以只需取一次d2值计算,避免重复运算;优先检查d2是否在d1中,存在则直接返回,否则通过绝对值差找到最接近的日期 - 格式转换:最后把日期转回字符串格式,和期望结果的格式保持统一
运行代码后即可得到符合要求的DataFrame。
内容的提问来源于stack exchange,提问作者josepmaria
相关产品推荐
相关产品推荐

