pandas按位置对指定列应用条件赋值的实现及报错解决
pandas按位置对指定列做条件赋值的实现方案
问题背景
按行位置对pandas DataFrame的指定列做分段处理时,代码运行出现值缺失、长度不匹配报错,相关信息如下:
样例数据与需求
import pandas as pd data = {'Pop': [728375, 733355, 695395, 734658, 732811, 789396, 727761, 751967], 'Pop2': [728375, 733355, 695395, 734658, 732811, 789396, 727761, 751967]} PopDF = pd.DataFrame(data) remainder = 6
需求规则:
PopDF['Pop2']列中,索引0到remainder位置的单元格值统一减1- 该列其余单元格,保留
Pop列对应行的原始值
错误写法与现象
尝试的两段代码均未达到预期:
- 第一段代码:
PopDF['Pop2']= PopDF['Pop2'].iloc[:(remainder)]-1
运行结果:前remainder行的减1操作生效,但剩余行全部变为NaN
2. 第二段代码:
PopDF['Pop2'].iloc[(remainder):] = PopDF['Pop'].iloc[(remainder):]
运行直接抛出报错:
ValueError: Length of values (1) does not match length of index (8)
错误原因说明
- 第一段代码:
PopDF['Pop2'].iloc[:(remainder)]-1返回的是长度为remainder的Series,赋值给整列时pandas会按索引对齐,短Series未覆盖的索引匹配不到有效值,就会被填充为NaN - 第二段代码:
PopDF['Pop2'].iloc[xxx]属于链式索引,pandas无法确认操作对象是原DataFrame的视图还是副本,会触发赋值校验报错,这种写法本身也不被pandas官方推荐,极易出现赋值不生效的问题
正确实现代码
最简洁的实现逻辑是先统一给Pop2列赋值为Pop列的全量值,再对目标位置做减1操作,全程避免链式索引:
# 先将Pop2列全量替换为Pop列的值,满足非目标位置的取值要求 PopDF['Pop2'] = PopDF['Pop'] # 对前remainder行的Pop2列做减1操作 # 注意:iloc切片为左闭右开规则,如果需要包含索引为remainder的行,将切片改为:remainder+1即可 PopDF.iloc[:remainder, PopDF.columns.get_loc('Pop2')] -= 1
如果需要分步处理两段逻辑,也可以用如下写法,效果完全一致:
# 处理前remainder行 PopDF.iloc[:remainder, PopDF.columns.get_loc('Pop2')] = PopDF.iloc[:remainder, PopDF.columns.get_loc('Pop2')] - 1 # 处理剩余行 PopDF.iloc[remainder:, PopDF.columns.get_loc('Pop2')] = PopDF.iloc[remainder:, PopDF.columns.get_loc('Pop')]
内容的提问来源于stack exchange,提问作者PCMitchell
相关产品推荐
相关产品推荐

