如何用Pandas判断上一行同名不同TrainingID并统计培训完成情况
Python统计人员培训完成情况解决方案
需求说明
- 读取含
Name(姓名)和TrainingID(培训ID)列的CSV文件 - 判断当前行与上一行是否为同一姓名且培训ID不同
- 最终输出每位人员完成的培训列表
示例CSV数据
Name, TrainingID John,1 John,2 Pete,1 James,1 James,2 James,3 Clint,1 Clint,2 Herb,1 Bob,1
原代码问题分析
原代码的核心错误:
- 误用
df.duplicated().any():该方法是检查整个DataFrame是否存在重复项,而非逐行与上一行对比 - 笔误:
subset=['nd']应为subset=['Name'] - 逻辑错误:每次循环都基于全表判断,导致重复输出"impossible"
解决方案
方法1:分组统计(推荐,高效简洁)
直接按姓名分组,收集每位人员的培训ID列表,无需逐行循环:
import pandas as pd def get_training_summary(): # 读取CSV,自动忽略列名前的空格 df = pd.read_csv("solitude.csv", skipinitialspace=True) # 按姓名分组,生成培训完成列表 training_summary = df.groupby('Name')['TrainingID'].apply(list).reset_index(name='CompletedTrainings') # 打印结果 for _, row in training_summary.iterrows(): print(f"{row['Name']} 完成的培训:{row['CompletedTrainings']}") return training_summary # 调用函数 get_training_summary()
输出结果:
Bob 完成的培训:[1] Clint 完成的培训:[1, 2] Herb 完成的培训:[1] James 完成的培训:[1, 2, 3] John 完成的培训:[1, 2] Pete 完成的培训:[1]
方法2:逐行对比(满足行与行判断需求)
使用shift()获取上一行数据,逐行判断姓名和培训ID的变化:
import pandas as pd def check_row_changes(): df = pd.read_csv("solitude.csv", skipinitialspace=True) # 添加列存储上一行的姓名和培训ID df['PrevName'] = df['Name'].shift(1) df['PrevTrainingID'] = df['TrainingID'].shift(1) for _, row in df.iterrows(): # 第一行无前置行,标记为新人员 if pd.isna(row['PrevName']): print(f"新人员:{row['Name']},培训ID:{row['TrainingID']}") else: if row['Name'] == row['PrevName']: if row['TrainingID'] != row['PrevTrainingID']: print(f"{row['Name']} 新增培训:{row['TrainingID']}") else: print(f"{row['Name']} 重复培训:{row['TrainingID']}") else: print(f"新人员:{row['Name']},培训ID:{row['TrainingID']}") # 调用函数 check_row_changes()
输出结果:
新人员:John,培训ID:1 John 新增培训:2 新人员:Pete,培训ID:1 新人员:James,培训ID:1 James 新增培训:2 James 新增培训:3 新人员:Clint,培训ID:1 Clint 新增培训:2 新人员:Herb,培训ID:1 新人员:Bob,培训ID:1
内容的提问来源于stack exchange,提问作者Yoep van Diepen
相关产品推荐
相关产品推荐

