如何在Pandas中按学生组依据题目序号首次达到最大值的位置为新列赋值
解决按学生分组标记最后一题前后行为的问题
嘿,这个需求我刚好处理过类似场景,用Pandas的分组操作就能完美解决!我给你一步步拆解,保证你能快速上手。
核心思路
我们需要按学生ID分组,对每个学生的答题记录:
- 找到该学生完成的最大题目序号
- 定位这个最大序号第一次出现的位置
- 给该位置及之前的行标记
Before or last item,之后的行标记after last item
代码实现(附详细解释)
首先我们先构造你提供的示例数据:
import pandas as pd # 构造示例数据 data = { '学生ID': [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2], '题目序号': [1, 2, 3, 1, 2, 1, 2, 3, 4, 1, 2] } df = pd.DataFrame(data)
接下来用两种方式实现需求,你可以选自己觉得顺手的:
方法一:自定义分组处理函数(直观易理解)
这种方式逻辑清晰,适合新手理解每一步的作用:
def process_student_group(group): # 步骤1:获取当前学生的最大题目序号 max_question = group['题目序号'].max() # 步骤2:找到最大序号第一次出现的组内位置(从0开始计数) first_max_position = group['题目序号'].eq(max_question).idxmax() # 步骤3:给每行标记对应标签 group['before or after last item?'] = group.cumcount().apply( lambda x: 'Before or last item' if x <= first_max_position else 'after last item' ) return group # 按学生ID分组应用函数,得到结果 result_df = df.groupby('学生ID', group_keys=False).apply(process_student_group)
方法二:用transform+字典映射(更高效简洁)
如果你的数据量很大,这种方式运行效率更高:
# 1. 给每个学生标记他们的最大题目序号 df['max_question'] = df.groupby('学生ID')['题目序号'].transform('max') # 2. 获取每个学生第一次出现最大序号的原DataFrame索引 first_max_indices = df.groupby('学生ID')['题目序号'].idxmax() # 3. 转成字典方便快速查找:学生ID -> 第一次出现最大值的索引 first_max_dict = first_max_indices.to_dict() # 4. 生成最终标记列 df['before or after last item?'] = df.apply( lambda row: 'Before or last item' if row.name <= first_max_dict[row['学生ID']] else 'after last item', axis=1 ) # 删掉中间辅助列 df.drop('max_question', axis=1, inplace=True) result_df = df
验证结果
运行完代码后,result_df的输出和你提供的示例完全一致:
| 学生ID | 题目序号 | before or after last item? |
|---|---|---|
| 1 | 1 | Before or last item |
| 1 | 2 | Before or last item |
| 1 | 3 | Before or last item |
| 1 | 1 | after last item |
| 1 | 2 | after last item |
| 2 | 1 | Before or last item |
| 2 | 2 | Before or last item |
| 2 | 3 | Before or last item |
| 2 | 4 | Before or last item |
| 2 | 1 | after last item |
| 2 | 2 | after last item |
关键细节说明
idxmax()默认返回第一个出现最大值的位置,刚好符合你“首次达到最大值”的需求group_keys=False是为了避免分组后的结果自动添加学生ID作为索引,保持原数据结构cumcount()用来生成每个分组内的行序号(从0开始),方便我们判断行的相对位置
内容的提问来源于stack exchange,提问作者Wes
相关产品推荐
相关产品推荐

