为什么使用Pandas配合np.nan替换CSV中低于阈值的数值不生效?
问题根本原因
你遇到的失效问题核心是**链式索引(Chained Indexing)**的副作用:df.loc[i]['arm_L']['x']这种连续多次索引的写法,pandas无法保证返回的是原DataFrame的视图还是副本:
- 列数少的窄DataFrame时,刚好返回视图,修改会同步到原数据
- 列数多的宽DataFrame时,返回的是临时副本,修改只作用于副本,不会影响原DataFrame,所以看起来替换失效
正确解决方案
方案1:向量化批量替换(推荐,效率远高于遍历)
直接用布尔索引定位所有需要替换的位置,一次性修改,完全避免索引问题:
import pandas as pd import numpy as np absolute_path = 'mypath/example.csv' p_cutoff = 0.9 df = pd.read_csv(absolute_path, header=[1,2], index_col=0) print('before: ') print(df.isna().sum()) # 直接定位arm_L下likelihood低于阈值的行,批量替换x、y为NaN mask = df[('arm_L', 'likelihood')] < p_cutoff df.loc[mask, ('arm_L', 'x')] = np.nan df.loc[mask, ('arm_L', 'y')] = np.nan print('') print('after: ') print(df.isna().sum())
方案2:兼容原有遍历逻辑的修改(不推荐,仅做逻辑对齐)
把链式索引合并为单次.loc调用,保证修改直接作用于原DataFrame:
for i, row in df.iterrows(): if df.loc[i, ('arm_L', 'likelihood')] < p_cutoff: # 用tuple指定多级列名,单次loc操作避免链式索引 df.loc[i, ('arm_L', 'x')] = np.nan df.loc[i, ('arm_L', 'y')] = np.nan
扩展适配所有身体部位
如果需要对所有身体部位的坐标都做置信度过滤,可以批量遍历一级列名统一处理:
# 获取所有身体部位的一级列名(自动去重) body_parts = df.columns.get_level_values(0).unique() p_cutoff = 0.9 for part in body_parts: mask = df[(part, 'likelihood')] < p_cutoff df.loc[mask, (part, 'x')] = np.nan df.loc[mask, (part, 'y')] = np.nan
内容的提问来源于stack exchange,提问作者ZL905
相关产品推荐
相关产品推荐

