You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将DataFrame每行异常值替换为NaN?现有代码致全表NaN求解决

问题:替换DataFrame每行异常值为NaN后全表变NaN的原因及修正

我尝试使用以下代码将DataFrame每行中的异常值替换为NaN,但运行后整个DataFrame都变为NaN,请问我哪里出错了?
附尝试的代码:

import pandas as pd

data = [['ANJSHD12', 140, 8, 99992, 0, 0, 0, 0, 1, 99999, 0,0, 0],
    ['ANJSHD15',10, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0], 
    ['ANJSHD17',19, 18, 22, 19, 25, 18, 23, 22, 22, 17,16, 19]]
df = pd.DataFrame(data, columns=['MATRÍCULA','V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7', 'V8', 'V9', 'V10','V11', 'V12'])

range_cols = list(df.columns.values)[1:13]

q1 = df[range_cols].quantile(0.25, axis=1)
q3 = df[range_cols].quantile(0.75, axis=1)
iqr = q3-q1 #interquartile range
min_val  = df.min(axis=1)
max_val = q3+3*iqr
df_filtered = df[(df[range_cols] > min_val) & (df[range_cols] < max_val)]

错误原因分析

  • 非数值列干扰最小值计算:使用df.min(axis=1)时包含了字符串类型的MATRÍCULA列,导致min_val成为字符串与数值混合的Series,和数值列比较时逻辑失效。
  • 布尔索引形状不匹配:布尔矩阵仅对应12个数值列,但原DataFrame有13列,第一列无对应布尔判断,直接被置为NaN。
  • 广播逻辑错误:min_val和max_val是每行单个值的Series,直接与每行12个值的DataFrame比较时,广播方向错误,无法实现“逐元素和本行上下界对比”的需求。

修正后的代码

针对数值列逐行判断异常值,替换为NaN后合并回原DataFrame:

方法一:利用同形状DataFrame实现逐元素比较

import pandas as pd

data = [['ANJSHD12', 140, 8, 99992, 0, 0, 0, 0, 1, 99999, 0,0, 0],
    ['ANJSHD15',10, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0], 
    ['ANJSHD17',19, 18, 22, 19, 25, 18, 23, 22, 22, 17,16, 19]]
df = pd.DataFrame(data, columns=['MATRÍCULA','V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7', 'V8', 'V9', 'V10','V11', 'V12'])

# 提取数值列
num_cols = df.columns[1:]

# 计算每行的四分位数、IQR及上下界
q1 = df[num_cols].quantile(0.25, axis=1)
q3 = df[num_cols].quantile(0.75, axis=1)
iqr = q3 - q1
# 若需沿用原逻辑用最小值当下界,替换为 df[num_cols].min(axis=1)
lower_bound = q1 - 3 * iqr
upper_bound = q3 + 3 * iqr

# 将上下界转换为与数值列同形状的DataFrame
lower_bound_df = pd.DataFrame([lower_bound]*len(num_cols)).T
lower_bound_df.columns = num_cols
upper_bound_df = pd.DataFrame([upper_bound]*len(num_cols)).T
upper_bound_df.columns = num_cols

# 替换异常值为NaN
df_cleaned = df.copy()
df_cleaned[num_cols] = df[num_cols].mask((df[num_cols] < lower_bound_df) | (df[num_cols] > upper_bound_df))

print(df_cleaned)

方法二:逐行apply处理

import pandas as pd

data = [['ANJSHD12', 140, 8, 99992, 0, 0, 0, 0, 1, 99999, 0,0, 0],
    ['ANJSHD15',10, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0], 
    ['ANJSHD17',19, 18, 22, 19, 25, 18, 23, 22, 22, 17,16, 19]]
df = pd.DataFrame(data, columns=['MATRÍCULA','V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7', 'V8', 'V9', 'V10','V11', 'V12'])

num_cols = df.columns[1:]

def replace_row_outliers(row):
    num_vals = row[num_cols]
    q1 = num_vals.quantile(0.25)
    q3 = num_vals.quantile(0.75)
    iqr = q3 - q1
    upper = q3 + 3 * iqr
    # 若需用最小值当下界,替换为 num_vals.min()
    lower = q1 - 3 * iqr
    num_vals[(num_vals < lower) | (num_vals > upper)] = pd.NA
    return row

df_cleaned = df.apply(replace_row_outliers, axis=1)
print(df_cleaned)

内容的提问来源于stack exchange,提问作者Jaribel Pokasideia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 09:09:19