Python无pandas场景下2D数组快速去除异常值的实现方案
3σ异常值快速过滤方案
首先直接给出优化后的实现,完全基于向量化操作,1000x8量级的数据集处理耗时可控制在1ms以内,远优于原有双重循环实现。
方案1:按样本过滤(推荐,符合绝大多数数据处理场景)
该方案逻辑为:只要某一个样本的任意特征符合异常值判定规则,就将整个样本删除,最终返回规整的二维数组,避免原有实现中逐列过滤导致的各列长度不一致、无法拼接为合法numpy数组的问题。
import numpy as np from scipy.stats import zscore def remove_outlier_fast(data, sigma_threshold: int = 3): # 对每个特征(列维度axis=0)计算z-score,如果需要按行计算改为axis=1即可 z_scores = zscore(data, axis=0) # 生成布尔掩码:仅保留所有特征z-score绝对值都小于阈值的样本 valid_mask = (np.abs(z_scores) < sigma_threshold).all(axis=1) return data[valid_mask]
方案2:按列独立过滤(匹配原有代码逻辑)
如果你确实需要对每个特征单独过滤异常值,最终返回各特征独立的过滤结果,可使用以下实现:
import numpy as np from scipy.stats import zscore def remove_outlier_per_column(data, sigma_threshold: int = 3): z_scores = zscore(data, axis=0) valid_mask = np.abs(z_scores) < sigma_threshold # 逐列返回过滤后的结果,返回为数组组成的列表 return [data[valid_mask[:, col_idx], col_idx] for col_idx in range(data.shape[1])]
注意事项
原有实现存在两个明显问题:
- 代码中未定义变量
i,直接运行会抛出NameError - 逐列过滤后如果各列保留的元素数量不一致,强制转换为numpy数组会生成object类型的异构数组,后续处理极易报错
如果你的计算环境无法导入scipy,也可以用纯numpy手动实现z-score计算,速度差异极小:
def remove_outlier_fast_numpy_only(data, sigma_threshold: int =3): mean = np.mean(data, axis=0, keepdims=True) std = np.std(data, axis=0, keepdims=True) z_scores = (data - mean) / std valid_mask = (np.abs(z_scores) < sigma_threshold).all(axis=1) return data[valid_mask]
内容的提问来源于stack exchange,提问作者Lukas S
相关产品推荐
相关产品推荐

