使用iterrows时index-1引发新增行及最后一行jum_mnth未赋值问题
问题分析与修正
原始数据
| pernr | plans | mnth | jum_mnth |
|---|---|---|---|
| 123 | 000 | 1 | NaN |
| 123 | 001 | 3 | NaN |
| 123 | 001 | 6 | NaN |
| 789 | 002 | 10 | NaN |
| 789 | 003 | 2 | NaN |
| 789 | 003 | 2 | NaN |
| 789 | 002 | 2 | NaN |
需求
将mnth的累计值赋值给jum_mnth,赋值条件为:
- 当前行是同一
plans的最后一行 - 当前行是同一
pernr的最后一行
编写的代码
for index, row in que.iterrows(): if row['pernr'] != nipp: que_cop.at[index-1, 'jum_mnth'] = mon nipp = row['pernr'] plan = row['plans'] mon = row['mnth'] else: if row['plans'] == plan: mon = mon + row['mnth'] else: que_cop.at[index-1, 'jum_mnth'] = mon print(str(nipp),plan,str(mon)) plan = row['plans'] mon = row['mnth'] if index == que_cop.index[-2]: que_cop.at[index, 'jum_mnth'] = mon
实际执行结果
| pernr | plans | mnth | jum_mnth |
|---|---|---|---|
| 123 | 000 | 1 | 1.0 |
| 123 | 001 | 3 | NaN |
| 123 | 001 | 6 | 9.0 |
| 789 | 002 | 10 | 10.0 |
| 789 | 003 | 2 | NaN |
| 789 | 003 | 2 | 4.0 |
| 789 | 002 | 2 | NaN |
| NaN | NaN | NaN | 0.0 |
预期结果
| pernr | plans | mnth | jum_mnth |
|---|---|---|---|
| 123 | 000 | 1 | 1 |
| 123 | 001 | 3 | NaN |
| 123 | 001 | 6 | 9 |
| 789 | 002 | 10 | 10 |
| 789 | 003 | 2 | NaN |
| 789 | 003 | 2 | 4 |
| 789 | 002 | 2 | 2 |
问题原因
- 变量未初始化导致新增行:代码开头未对
nipp、plan、mon初始化,第一次循环时row['pernr'] != nipp触发,此时index-1为-1,Pandas会自动新增索引为-1的空行(即结果末尾的NaN行)。 - 最后一行处理逻辑错误:用
index == que_cop.index[-2]判断处理最后一行,但que_cop.index[-2]是倒数第二行的索引,导致真正的最后一行未被赋值,jum_mnth仍为NaN。 - 分组累计逻辑遗漏:当循环到
pernr的最后一行时,即使plans未变化,也需要将累计值赋值给该行的jum_mnth,原代码未覆盖此场景。
修正后的代码
# 初始化变量,避免首次循环报错 nipp = None plan = None mon = 0 que_cop = que.copy() # 深拷贝原数据,避免修改原表 for index, row in que.iterrows(): if nipp is None: # 处理第一行,初始化分组变量 nipp = row['pernr'] plan = row['plans'] mon = row['mnth'] else: if row['pernr'] != nipp: # 切换pernr,将上一组的累计值赋值给上一行 que_cop.at[index-1, 'jum_mnth'] = mon # 重置分组变量 nipp = row['pernr'] plan = row['plans'] mon = row['mnth'] else: if row['plans'] != plan: # 同一pernr下切换plans,将上一个plans的累计值赋值给上一行 que_cop.at[index-1, 'jum_mnth'] = mon # 重置plans和累计值 plan = row['plans'] mon = row['mnth'] else: # 同一pernr同一plans,累计mnth值 mon += row['mnth'] # 循环结束后处理最后一行,确保累计值被赋值 que_cop.at[que_cop.index[-1], 'jum_mnth'] = mon
修正说明
- 新增变量初始化,避免首次循环访问无效索引导致新增空行。
- 移除错误的倒数第二行判断,改为循环结束后单独处理最后一行,保证最后一行的累计值正确赋值。
- 理顺分组逻辑:先判断
pernr变化,再判断plans变化,同一组内累计数值,分组切换时赋值上一组的累计结果。
内容的提问来源于stack exchange,提问作者biyazelnut
相关产品推荐
相关产品推荐

