如何为Pandas DataFrame的重复分组创建规则:保留最早记录并基于组内特征批量设置列值
解决Pandas分组保留最早记录并标记组内特征的问题
这问题我之前处理类似需求时碰到过,用Pandas的分组聚合功能就能轻松实现你的需求,给你两种可行的方案,适合不同的理解习惯:
方案一:一步聚合完成(高效简洁)
这种方法直接通过groupby+agg一步得到结果,代码量少,处理大型DataFrame时效率更高:
import pandas as pd # 生成原DataFrame(和你的代码一致) dates = pd.to_datetime(['2021-1-1', '2017-2-1', '2016-5-1', '2020-6-1', '2020-11-1', '2012-4-1']) animals = pd.Series(['cat', 'dog', 'dog', 'cat', 'fish', 'fish']) df = pd.DataFrame({'DoB' : dates, 'Animal' : animals}) df[r'Born in 2020?'] = df['DoB'].apply(lambda x: x.year == 2020) # 核心处理代码 result_df = df.groupby('Animal').agg( DoB=('DoB', 'min'), # 取每组最早的出生日期 'Duplicate born in 2020?'=('Born in 2020?', 'any') # 判断组内是否有2020年出生的记录 ).reset_index() # 调整列顺序和示例输出一致 result_df = result_df[['DoB', 'Animal', 'Duplicate born in 2020?']] print(result_df)
代码解释:
groupby('Animal'):按动物种类对DataFrame分组agg():聚合操作,同时完成两个任务:('DoB', 'min'):对每个组的DoB列取最小值,即该动物的最早出生日期('Born in 2020?', 'any'):对每个组的布尔列用any()判断,只要组内有一条记录为True,结果就为True
reset_index():把Animal从分组索引变回普通列,保证结构和需求一致
方案二:分步处理(逻辑清晰)
如果觉得一步聚合有点抽象,也可以拆成分步骤执行,逻辑更直观:
import pandas as pd # 生成原DataFrame dates = pd.to_datetime(['2021-1-1', '2017-2-1', '2016-5-1', '2020-6-1', '2020-11-1', '2012-4-1']) animals = pd.Series(['cat', 'dog', 'dog', 'cat', 'fish', 'fish']) df = pd.DataFrame({'DoB' : dates, 'Animal' : animals}) df[r'Born in 2020?'] = df['DoB'].apply(lambda x: x.year == 2020) # 步骤1:标记每组中最早的记录 df['is_earliest'] = df.groupby('Animal')['DoB'].transform(lambda x: x == x.min()) # 步骤2:计算每个动物组的"是否有2020年出生记录"标记 group_flag = df.groupby('Animal')['Born in 2020?'].any().reset_index(name='Duplicate born in 2020?') # 步骤3:筛选最早记录并合并标记 result_df = df[df['is_earliest']].merge(group_flag, on='Animal') # 步骤4:删除不需要的列并调整顺序 result_df = result_df.drop(columns=['Born in 2020?', 'is_earliest'])[['DoB', 'Animal', 'Duplicate born in 2020?']] print(result_df)
代码解释:
transform(lambda x: x == x.min()):给每组中最早的记录标记为True,其他为Falsegroupby('Animal')['Born in 2020?'].any():单独计算每个组的标记结果merge(group_flag, on='Animal'):把标记结果合并到筛选出的最早记录行中- 最后清理多余列,调整列顺序到需求格式
两种方案运行后都会得到你期望的结果:
| DoB | Animal | Duplicate born in 2020? | |
|---|---|---|---|
| 0 | 2020-06-01 | cat | True |
| 1 | 2016-05-01 | dog | False |
| 2 | 2012-04-01 | fish | True |
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

