Python遍历DataFrame列调用IQR去离群值函数报str类型运算错误
错误原因
报错TypeError: unsupported operand type(s) for -: 'str' and 'str'的核心诱因是遍历列时未做类型过滤:delete_outlier_IQR函数默认遍历DataFrame的全部列,包括存储字符串、分类标签的非数值类型列。对非数值列调用quantile()计算分位数时,返回结果为字符串类型,执行IQR = Q3 - Q1数值减法运算时,字符串类型不支持该操作,直接触发类型错误。
除此之外原代码还有两处逻辑问题:
- 仅计算了离群值的索引、打印了占比提示,没有实际执行离群值删除操作,运行后DataFrame不会发生任何修改
- 函数直接依赖全局变量
df,复用性差,容易因为全局变量意外改动触发其他异常
修复方案
- 遍历列时仅筛选数值类型列,跳过所有非数值列,从根源上避免对字符串执行数值运算的问题,可直接通过
df.select_dtypes(include='number').columns获取所有数值列名 - 补全离群值过滤逻辑,将DataFrame作为参数传入函数,消除全局变量依赖
- 修复后可直接运行的代码如下:
def remove_outlier_IQR(input_df, feature): Q1 = input_df[feature].quantile(0.25) Q3 = input_df[feature].quantile(0.75) IQR = Q3 - Q1 upbound = Q3 + 6 * IQR downbound = Q1 - 6 * IQR # 构造非离群值的筛选条件 keep_cond = ~((input_df[feature] < downbound) | (input_df[feature] > upbound)) outlier_count = len(input_df) - keep_cond.sum() outlier_percent = outlier_count / len(input_df) if outlier_percent > 0.1: print(f'列[{feature}] 离群值占比 {outlier_percent:.2%},超过10%') else: print(f'列[{feature}] 离群值占比 {outlier_percent:.2%},低于10%') # 返回过滤当前列离群值后的DataFrame return input_df[keep_cond] def delete_outlier_IQR(input_df): process_df = input_df.copy() # 仅对数值类型列做离群值处理 for col in process_df.select_dtypes(include='number').columns: process_df = remove_outlier_IQR(process_df, col) return process_df # 调用方式:将处理后结果赋值回原df即可 # df = delete_outlier_IQR(df)
补充说明:上述逐列处理的逻辑是每处理一列就删除对应离群行,后续列的IQR计算基于过滤后的数据集执行。如果需要基于原始全量数据计算所有列的离群值后统一删除,可以先收集所有离群行的索引去重,再一次性完成行删除。
内容的提问来源于stack exchange,提问作者Derrick Nguyen
相关产品推荐
相关产品推荐

