如何基于Name列从Pandas DataFrame获取最小/最大日期
Pandas 多格式日期列分组聚合问题解决
问题背景
原始DataFrame数据:
| Name | Date1 | Date2 |
|---|---|---|
| One | 199007 | 199010 |
| One | 199206 | 199206 |
| One | 199505 | 199505 |
| Two | 19880701 | 19880701 |
| Two | 19980704 | 19980704 |
| Three | 2020 | 2020 |
| Three | 2022 | 2022 |
需求:按Name分组,对Date1取最小值,Date2取最大值,预期输出:
| Name | Date1 | Date2 |
|---|---|---|
| One | 199007 | 199505 |
| Two | 19880701 | 19980704 |
| Three | 2020 | 2022 |
遇到的问题:
- 直接调用
pd.to_datetime(df['Date1'])时,报错month must be in 1...12 199007,无法识别yyyymm格式 - 指定
format='%Y%m%d'并设置errors='ignore',仅跳过错误但未完成日期转换,无法进行后续的极值计算
解决方案
1. 统一转换日期为标准datetime类型
针对多种日期格式,先清理字符串(去掉分隔符-),再根据字符串长度补全为yyyymmdd格式,最后转换为datetime:
import pandas as pd def parse_date(date_str): # 去除分隔符,统一为纯数字字符串 clean_str = str(date_str).replace('-', '') # 根据长度补全为8位日期串 if len(clean_str) == 4: return f"{clean_str}0101" # 年份补1月1日 elif len(clean_str) == 6: return f"{clean_str}01" # 年月补当月1日 elif len(clean_str) == 8: return clean_str # 完整日期直接返回 else: return pd.NaT # 异常格式返回空值 # 转换Date1和Date2列 df['Date1'] = pd.to_datetime(df['Date1'].apply(parse_date), format='%Y%m%d') df['Date2'] = pd.to_datetime(df['Date2'].apply(parse_date), format='%Y%m%d')
2. 分组聚合并还原原始日期格式
分组计算极值后,根据每个Name对应的原始日期长度,将datetime类型还原为原有格式:
# 分组计算Date1最小值、Date2最大值 grouped_df = df.groupby('Name').agg( min_date1=('Date1', 'min'), max_date2=('Date2', 'max') ).reset_index() # 获取每个Name对应的原始日期长度(取该组第一条记录的日期长度) name_date_len = df.groupby('Name').apply( lambda x: len(str(x['Date1'].iloc[0]).replace('-', '')) ).to_dict() def restore_date_format(date_obj, target_len): if pd.isna(date_obj): return None # 根据目标长度返回对应格式 if target_len == 4: return date_obj.strftime('%Y') elif target_len == 6: return date_obj.strftime('%Y%m') elif target_len == 8: return date_obj.strftime('%Y%m%d') else: return date_obj.strftime('%Y-%m-%d') # 处理带分隔符的原始格式 # 还原日期格式 grouped_df['Date1'] = grouped_df.apply( lambda row: restore_date_format(row['min_date1'], name_date_len[row['Name']]), axis=1 ) grouped_df['Date2'] = grouped_df.apply( lambda row: restore_date_format(row['max_date2'], name_date_len[row['Name']]), axis=1 ) # 保留所需列 final_result = grouped_df[['Name', 'Date1', 'Date2']] print(final_result)
执行上述代码后,即可得到预期的分组聚合结果。
内容的提问来源于stack exchange,提问作者Rag
相关产品推荐
相关产品推荐

