Pandas按Acc_id分组取最新end_date生成新列的实现方法
分组新增组内最大日期列实现方案
你之前用group by、pivot没得到正确结果,核心原因是方法逻辑不匹配:pivot用于行列转换,完全不适用当前需求;普通group by聚合后会返回按分组压缩的结果,无法直接把聚合值匹配回原表每一行,另外要注意你的日期列是字符串格式,直接比大小会得到错误结果。
下面给两种最常用场景的可直接运行的实现:
SQL 实现(通用所有SQL引擎)
写法1:窗口函数(推荐,性能最优写法最简)
用窗口函数按Acc_id分区,直接给每一行计算同组的最大end_date,不需要关联表:
SELECT Acc_id, Crt_id, start_date, end_date, -- 计算最大日期后转回原表的月/日/年格式 DATE_FORMAT( MAX(STR_TO_DATE(end_date, '%m/%d/%y')) OVER (PARTITION BY Acc_id), '%c/%e/%y' ) AS Acc_end_date FROM your_table;
不同数据库日期转换函数调整:PostgreSQL/Oracle把
STR_TO_DATE换成TO_DATE(xxx, 'MM/DD/YY'),DATE_FORMAT换成TO_CHAR(xxx, 'MM/DD/YY');SQL Server用CONVERT(DATE, end_date, 1)做转换,CONVERT(VARCHAR, xxx, 1)转回去。
写法2:聚合+左关联(兼容不支持窗口函数的老版本数据库)
先按Acc_id分组算出每个账号的最晚结束日期,再通过左关联把值匹配回原表:
SELECT t1.Acc_id, t1.Crt_id, t1.start_date, t1.end_date, t2.acc_max_end AS Acc_end_date FROM your_table t1 LEFT JOIN ( SELECT Acc_id, DATE_FORMAT(MAX(STR_TO_DATE(end_date, '%m/%d/%y')), '%c/%e/%y') AS acc_max_end FROM your_table GROUP BY Acc_id ) t2 ON t1.Acc_id = t2.Acc_id;
Python Pandas 实现
用groupby+transform直接生成和原表长度一致的分组最大值序列,不需要额外join:
import pandas as pd # 1. 读取数据,替换成你自己的数据读取逻辑 df = pd.read_csv("your_data.csv") # 2. 把字符串格式的end_date转成日期类型,避免字符串比大小出错 df["end_date_dt"] = pd.to_datetime(df["end_date"], format="%m/%d/%y") # 3. 分组计算每个Acc_id下的最大end_date,转回原日期格式 df["Acc_end_date"] = ( df.groupby("Acc_id")["end_date_dt"] .transform("max") .dt.strftime("%-m/%-d/%y") # Windows系统把格式串改成"%#m/%#d/%y" ) # 4. 删除临时用的日期辅助列 df = df.drop(columns=["end_date_dt"])
避坑提示
- 所有日期计算必须先转成日期/时间类型,不能直接用字符串比大小:比如字符串
"12/1/11"字典序比"1/31/18"大,会导致最大值计算完全错误。 - 普通
group by聚合后返回的是每个分组1行的压缩结果,要把聚合值放回原表每一行,要么用窗口函数,要么用聚合结果和原表做关联。
内容的提问来源于stack exchange,提问作者user13024918
相关产品推荐
相关产品推荐

