基于索引值的Pandas DataFrame条件填充技术问询
解决Pandas DataFrame中运动项目累计计数的问题
问题背景
我有一个存储夏令营学生运动活动信息的Pandas DataFrame,学生每次参与可选择有限的运动项目(示例中为3种)。DataFrame包含字段:Name(学生姓名)、Nr(到访次数/年份)、Activity(当年选择的运动项目),以及对应每个运动的计数列(如Football、Badminton、Swimming)。
输入DataFrame示例
Name Nr Activity Football Badminton Swimming Mike 1 Football 0 0 0 Mike 2 Football 0 0 0 Mike 3 Badminton 0 0 0 Mike 4 Football 0 0 0 Mike 5 Swimming 0 0 0
期望输出DataFrame示例
Name Nr Activity Football Badminton Swimming Mike 1 Football 1 0 0 Mike 2 Football 2 0 0 Mike 3 Badminton 2 1 0 Mike 4 Football 3 1 0 Mike 5 Swimming 3 1 1
核心需求:根据每行的Activity字段,将对应运动列从当前行开始的所有后续行(含当前行)累计计数。比如第3年选择羽毛球后,第4、5年的羽毛球列需保持累计的1次记录,后续每新增一次对应运动,计数继续累加。
解决方案
利用Pandas的向量化操作和cumsum()累计求和方法,可以高效实现需求,无需手动遍历修改索引行。
代码实现
- 首先构造输入DataFrame(如果已有数据可跳过此步骤):
import pandas as pd data = { 'Name': ['Mike']*5, 'Nr': [1,2,3,4,5], 'Activity': ['Football', 'Football', 'Badminton', 'Football', 'Swimming'], 'Football': [0,0,0,0,0], 'Badminton': [0,0,0,0,0], 'Swimming': [0,0,0,0,0] } df = pd.DataFrame(data)
- 处理运动列的累计计数:
# 定义所有运动项目列的名称 sport_columns = ['Football', 'Badminton', 'Swimming'] for sport in sport_columns: # 生成标记序列:当前行Activity等于该运动则标记为1,否则为0 sport_participation = df['Activity'] == sport # 计算累计和,赋值给对应运动列 df[sport] = sport_participation.cumsum()
- 查看结果:
print(df)
结果说明
运行后得到的DataFrame完全符合期望输出:
cumsum()会自动累计每个运动的参与次数,每行的运动列值代表到当前行为止该学生参与该运动的总次数。- 后续行如果未选择该运动,累计和不会变化,自然保持之前的累计值,完美满足“当前及后续行延续累计计数”的需求。
多学生场景适配
如果DataFrame包含多个学生,只需按Name分组后应用逻辑即可,确保每个学生的计数独立:
df = df.groupby('Name').apply(lambda x: x.assign(**{ sport: (x['Activity'] == sport).cumsum() for sport in sport_columns })).reset_index(drop=True)
内容的提问来源于stack exchange,提问作者user495490
相关产品推荐
相关产品推荐

