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

如何修复DataFrame按IQR过滤时出现的KeyError: '[x] not found in axis'

IQR异常值过滤时KeyError问题解决

问题描述

尝试用IQR(四分位距)对DataFrame的指定特征进行异常值过滤,代码如下:

import pandas as pd
import numpy as np

# Load data
df = pd.read_csv("dataframe.csv")
features = df.loc[:, ('col1, col2, col3, col4, col5')]
 
print("Old Shape: ", df.shape)

def filtering(column_name):
    print(column_name)
    Q1 = np.percentile(df[column_name], 25,
                   interpolation = 'midpoint')
 
    Q3 = np.percentile(df[column_name], 75,
                   interpolation = 'midpoint')
    IQR = Q3 - Q1
 
    # Upper bound
    upper = np.where(df[column_name] >= (Q3+1.5*IQR))
    # Lower bound
    lower = np.where(df[column_name] <= (Q1-1.5*IQR))
    
    ''' Removing the Outliers '''
    df.drop(upper[0], inplace = True)
    df.drop(lower[0], inplace = True)
    print("New Shape: ", df.shape)
    print('==== done ====')

for col in features.columns:
    filtering(col)

运行时在df.drop(lower[0], inplace=True)处报错:

KeyError: '[14] not found in axis'

错误原因

  1. 索引与行位置混淆:np.where()返回的是当前DataFrame中异常行的位置下标(从0开始的整数),但df.drop()默认按索引标签删除行。当之前删除过行后,DataFrame的索引不再连续,此时传入的位置下标对应的索引标签可能已被删除,触发KeyError。
  2. 逐步过滤的逻辑缺陷:循环处理每个特征时,每次删除行都会修改原DataFrame,后续特征的IQR计算基于已过滤后的数据集,导致过滤标准不断变化,同时可能重复尝试删除已被移除的行。
  3. 特征选取语法错误:原代码中features = df.loc[:, ('col1, col2, col3, col4, col5')]是错误的,该写法会将整个字符串当作单个列名查找,正确的多列选取应使用列表['col1', 'col2', 'col3', 'col4', 'col5']。

解决方案

方案一:修正删除逻辑,按位置匹配索引标签

修改drop操作,通过行位置获取对应索引标签后再删除,确保操作的是当前DataFrame中存在的行:

import pandas as pd
import numpy as np

# Load data
df = pd.read_csv("dataframe.csv")
# 修正特征选取语法
features = df.loc[:, ['col1', 'col2', 'col3', 'col4', 'col5']]
 
print("Old Shape: ", df.shape)

def filtering(column_name):
    print(column_name)
    Q1 = np.percentile(df[column_name], 25,
                   interpolation = 'midpoint')
 
    Q3 = np.percentile(df[column_name], 75,
                   interpolation = 'midpoint')
    IQR = Q3 - Q1
 
    # 获取异常行的位置下标
    upper_pos = np.where(df[column_name] >= (Q3+1.5*IQR))[0]
    lower_pos = np.where(df[column_name] <= (Q1-1.5*IQR))[0]
    
    # 通过位置下标获取对应索引标签并删除
    df.drop(df.index[upper_pos], inplace=True)
    df.drop(df.index[lower_pos], inplace=True)
    print("New Shape: ", df.shape)
    print('==== done ====')

for col in features.columns:
    filtering(col)

方案二:统一收集异常行索引,一次性删除(推荐)

如果希望基于原始数据集的IQR标准过滤所有特征的异常值(避免逐步过滤导致的标准偏移),可先收集所有需删除的索引,最后一次性删除:

import pandas as pd
import numpy as np

# Load data
df = pd.read_csv("dataframe.csv")
# 修正特征选取语法
features = df.loc[:, ['col1', 'col2', 'col3', 'col4', 'col5']]
original_df = df.copy()  # 保存原始数据用于计算统一的IQR标准
to_drop = set()

print("Old Shape: ", df.shape)

def get_outlier_indices(column_name):
    col_data = original_df[column_name]
    Q1 = np.percentile(col_data, 25, interpolation='midpoint')
    Q3 = np.percentile(col_data, 75, interpolation='midpoint')
    IQR = Q3 - Q1
    # 获取原始数据中的异常行索引
    upper_indices = original_df[col_data >= (Q3+1.5*IQR)].index
    lower_indices = original_df[col_data <= (Q1-1.5*IQR)].index
    return set(upper_indices) | set(lower_indices)

# 收集所有特征的异常行索引
for col in features.columns:
    outlier_indices = get_outlier_indices(col)
    to_drop.update(outlier_indices)
    print(f"{col} 找到 {len(outlier_indices)} 个异常值")

# 一次性删除所有异常行
df.drop(to_drop, inplace=True)
print("New Shape: ", df.shape)
print('==== done ====')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 10:40:30