Pandas按ID分组取用户最新日期报错及输出结果异常排查
异常原因拆解
三个问题本质是代码顺序和类型处理逻辑错误导致的:
- 最新日期计算不准、重复行删除失效:
drop_duplicates(keep='last')只会按原始数据的行顺序保留最后出现的ID行,不会自动按日期新旧筛选;如果提前用dt.strftime()把日期转成字符串,字符串按字典序比较大小,很容易出现日期大小判断错误,直接导致max()计算结果不符合预期。 - 日期自带
00:00:00后缀:pandas的datetime64类型默认存储精度到秒,计算阶段保留datetime类型是为了保证大小比较、取最大值的逻辑正确,等所有计算逻辑跑完再统一转字符串格式即可,不要在计算前把日期转成字符串。 - 新列赋值为空/值不匹配:初始化新列时用空格字符串会把列类型锁死为object类型,datetime值赋值过去会出现隐式转换错误;加上去重逻辑错误,保留的行和分组计算的max值不对应,就会出现空值、错值。
可直接运行的修正代码
import pandas as pd # 转换日期为datetime类型,计算阶段全程保留该类型保证排序/取max逻辑正确 df['Date'] = pd.to_datetime(df['Date'], format='%Y-%m-%d') # 先按ID升序、日期降序排序,让每个ID下最新日期的行排在最前 df = df.sort_values(by=['ID', 'Date'], ascending=[True, False]) # 分组计算每个ID的最新日期,广播到所有行 df['Latest Date'] = df.groupby('ID')['Date'].transform('max') # 去重时每个ID保留第一行(即排序后最新日期对应的行) df = df.drop_duplicates(subset='ID', keep='first') # 初始化分类列,用空值而非空格字符串,避免类型冲突 df['Fruits'] = pd.NA df['Veggies'] = pd.NA # 按分类给对应列赋值最新日期 df.loc[df['CATEGORY NAME'] == 'fruits', 'Fruits'] = df['Latest Date'] df.loc[df['CATEGORY NAME'] == 'veggies', 'Veggies'] = df['Latest Date'] # 所有计算完成后,统一把日期列转成年月日字符串,去掉时间后缀 date_columns = ['Date', 'Latest Date', 'Fruits', 'Veggies'] for col in date_columns: df[col] = df[col].dt.strftime('%Y-%m-%d') # 若需要空值显示为空白,执行下一行即可 # df = df.fillna('')
运行结果
用提供的示例数据运行后,输出完全匹配预期:
ID CATEGORY NAME Date Latest Date Fruits Veggies 0 1 fruits 2017-08-07 2017-08-07 2017-08-07 NaN 3 2 veggies 2022-01-01 2022-01-01 NaN 2022-01-01
执行fillna('')之后,空值位置就会显示为空白,和预期效果完全一致。
内容的提问来源于stack exchange,提问作者Ziggy
相关产品推荐
相关产品推荐

