Pandas如何将超出fence_high/fence_low范围的值替换为NaN
错误原因
你之前写的df_new = df[(df < df["fence_high"]) & (df > df["fence_low"])]无法实现需求,核心问题有两个:
- 方括号包裹布尔矩阵是pandas筛选整行的语法,不是修改单个单元格值的逻辑,会把不满足条件的整行全部处理,无法只替换异常位置的单元格
- 比较范围覆盖了整个DataFrame,连
fence_high、fence_low两个阈值列本身也参与了比较,而你实际只需要处理前三列,且阈值列本身不需要修改。
正确实现方法
用布尔定位匹配异常单元格,直接赋值为NaN即可,注意只选取前三列参与阈值比较:
# 备份原表,避免直接修改原始数据 df_new = df.copy() # 指定需要做异常值替换的前三列 target_cols = ["col1", "col2", "col3"] # 定义异常值判断条件:值大于等于上围栏 或 小于等于下围栏 outlier_condition = (df_new[target_cols] >= df_new[["fence_high"]].to_numpy()) | (df_new[target_cols] <= df_new[["fence_low"]].to_numpy()) # 所有满足异常条件的单元格替换为NaN df_new[target_cols] = df_new[target_cols].mask(outlier_condition)
运行代码后得到的结果和预期完全一致:
col1 col2 col3 fence_high fence_low 0 NaN 3.0 NaN 9.0 1.5 1 2.0 4.0 6.0 7.0 1.0 2 4.0 NaN NaN 6.5 0.0
小提示:代码中给
fence_high、fence_low调用.to_numpy()是为了关闭pandas默认的列名对齐机制,保证每一行的数值和对应行的阈值做比较,避免列名不匹配导致的广播错误。
内容的提问来源于stack exchange,提问作者Olivia
相关产品推荐
相关产品推荐

