网站首页 > 文章精选 正文
昨天介绍了数据的标准化处理方法《数据标准化(归一化)》,里面介绍了常见的方法。而且数据里面有异常值的情况下不同方法的作用性也不一样。今天就来详细介绍一下数据异常值的检测方法,以及如何处理异常值。
异常值检测与处理是数据清洗过程中的一个关键步骤,它涉及到识别和处理那些与大多数数据显著不同的数据点。异常值可能是由于数据录入错误、测量误差、数据损坏或其他原因造成的。处理异常值的目的是提高数据的质量,避免它们对分析结果产生不利影响。以下是异常值检测与处理的详细介绍。
【异常值检测】
整体分成6类13中方法来进行异常值的检测,目录如下↓
下面分别介绍一下每一种方法,然后通过正态分布和非正态分布两种数据进行演示,先把数据生成一下,代码和结果如下↓
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neighbors import LocalOutlierFactor
from sklearn.cluster import DBSCAN
from sklearn.ensemble import IsolationForest
from sklearn.svm import OneClassSVM
from sklearn.decomposition import PCA
from scipy import stats
from sklearn.mixture import GaussianMixture
# 生成正态分布和非正态分布数据集
np.random.seed(21)
X_normal = np.random.normal(loc=0, scale=3, size=100)
X_uniform = np.random.uniform(low=-5, high=5, size=100)
# 添加异常值
X_normal_with_outliers = np.append(X_normal, [10, 15, -10, -15])
X_uniform_with_outliers = np.append(X_uniform, [10, 15, -10, -15])
# 可视化函数
def plot_data(X, outliers, title):
plt.figure(figsize=(10, 6))
plt.scatter(range(len(X)), X, edgecolor='k', s=20, label='Data')
plt.scatter(outliers, X[outliers], color='red', edgecolor='k', s=50, label='Outliers')
plt.title(title)
plt.legend()
plt.show()
绘制图形↓
plt.hist(X_normal_with_outliers.flatten(), bins=50, color='blue', alpha=0.7)
plt.hist(X_uniform_with_outliers.flatten(), bins=30, color='green', alpha=0.7)
【统计方法-标准差法】
也称3σ准则,假设数据符合正态分布,通过计算均值和标准差,将超过均值±3倍标准差的值视为异常值。优点是简单易行,适用于正态分布的数据。缺点是对非正态分布的数据效果较差,对极端值敏感。
def detect_outliers_std(X):
mean = np.mean(X)
std = np.std(X)
outliers = np.where((X > mean + 3 * std) | (X < mean - 3 * std))
return outliers
outliers_std_normal = detect_outliers_std(X_normal_with_outliers)
outliers_std_uniform = detect_outliers_std(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_std_normal[0], 'Standard Deviation Method -正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_std_uniform[0], 'Standard Deviation Method -非正态分布+异常值')
【统计方法-Z-Score法】
标准化数据,根据Z值(通常±3)来检测异常值。优点是与标准差法类似,适用于正态分布的数据。缺点是同样对非正态分布的数据效果较差。
def detect_outliers_zscore(X):
z_scores = np.abs(stats.zscore(X))
outliers = np.where(z_scores > 3)
return outliers
outliers_zscore_normal = detect_outliers_zscore(X_normal_with_outliers)
outliers_zscore_uniform = detect_outliers_zscore(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_zscore_normal[0], 'Z-Score Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_zscore_uniform[0], 'Z-Score Method - 非正态分布+异常值')
【统计方法-箱线图法】
使用四分位数(Q1和Q3)和四分位距(IQR),超过Q1-1.5倍IQR或Q3+1.5倍IQR的值视为异常值。优点是适用于任何分布的数据,对数据分布的要求较低。缺点是对异常值比例较高的数据效果不佳。
def detect_outliers_iqr(X):
Q1 = np.percentile(X, 25)
Q3 = np.percentile(X, 75)
IQR = Q3 - Q1
outliers = np.where((X < Q1 - 1.5 * IQR) | (X > Q3 + 1.5 * IQR))
return outliers
outliers_iqr_normal = detect_outliers_iqr(X_normal_with_outliers)
outliers_iqr_uniform = detect_outliers_iqr(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_iqr_normal[0], 'IQR Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_iqr_uniform[0], 'IQR Method - 非正态分布+异常值')
【基于距离的方法-K-最近邻】
KNN,计算每个数据点与其最近的k个邻居的距离,显著大于其他点的距离则为异常值。优点是无需对数据分布有假设,适用于多维数据。缺点是计算复杂度较高,参数k的选择较敏感。
def detect_outliers_knn(X, k=3):
clf = LocalOutlierFactor(n_neighbors=k)
y_pred = clf.fit_predict(X.reshape(-1, 1))
outliers = np.where(y_pred == -1)
return outliers
outliers_knn_normal = detect_outliers_knn(X_normal_with_outliers)
outliers_knn_uniform = detect_outliers_knn(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_knn_normal[0], 'KNN Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_knn_uniform[0], 'KNN Method - 非正态分布+异常值')
【基于距离的方法-局部离群因子】
LOF,比较一个点与其邻居的局部密度,检测局部异常值。优点是能够检测局部异常值,适用于多维数据。缺点是参数选择较为复杂,计算复杂度较高。
def detect_outliers_lof(X, n_neighbors=20):
clf = LocalOutlierFactor(n_neighbors=n_neighbors)
y_pred = clf.fit_predict(X.reshape(-1, 1))
outliers = np.where(y_pred == -1)
return outliers
outliers_lof_normal = detect_outliers_lof(X_normal_with_outliers)
outliers_lof_uniform = detect_outliers_lof(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_lof_normal[0], 'LOF Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_lof_uniform[0], 'LOF Method - 非正态分布+异常值')
【基于密度的方法-DBSCAN】
基于密度的聚类方法,找到密度较低的区域来识别异常值。优点是能找到任意形状的聚类,适用于空间密度不均匀的数据。缺点是参数选择较为复杂,对高维数据效果较差。
def detect_outliers_dbscan(X, eps=0.5, min_samples=5):
clf = DBSCAN(eps=eps, min_samples=min_samples)
y_pred = clf.fit_predict(X.reshape(-1, 1))
outliers = np.where(y_pred == -1)
return outliers
outliers_dbscan_normal = detect_outliers_dbscan(X_normal_with_outliers)
outliers_dbscan_uniform = detect_outliers_dbscan(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_dbscan_normal[0], 'DBSCAN Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_dbscan_uniform[0], 'DBSCAN Method - 非正态分布+异常值')
【基于模型的方法-孤立森林】
Isolation Forest,基于随机森林的思想,构建多棵树,通过分裂的次数来衡量异常值。优点是适用于大数据集,对数据分布无假设。缺点是参数调优复杂,对小数据集效果不佳。
def detect_outliers_isolation_forest(X):
clf = IsolationForest(contamination=0.05)
y_pred = clf.fit_predict(X.reshape(-1, 1))
outliers = np.where(y_pred == -1)
return outliers
outliers_isolation_normal = detect_outliers_isolation_forest(X_normal_with_outliers)
outliers_isolation_uniform = detect_outliers_isolation_forest(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_isolation_normal[0], 'Isolation Forest Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_isolation_uniform[0], 'Isolation Forest Method - 非正态分布+异常值')
【基于模型的方法-一类支持向量机】
One-Class SVM,构建一个边界来识别异常值。优点是适用于高维数据,对数据分布无假设。缺点是计算复杂度高,对参数敏感。
def detect_outliers_one_class_svm(X):
clf = OneClassSVM(nu=0.05, kernel='rbf', gamma=0.1)
y_pred = clf.fit_predict(X.reshape(-1, 1))
outliers = np.where(y_pred == -1)
return outliers
outliers_one_class_svm_normal = detect_outliers_one_class_svm(X_normal_with_outliers)
outliers_one_class_svm_uniform = detect_outliers_one_class_svm(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_one_class_svm_normal[0], 'One-Class SVM Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_one_class_svm_uniform[0], 'One-Class SVM Method - 非正态分布+异常值')
【基于回归的方法-残差分析】
利用回归模型,分析残差,如果残差值过大,则可能是异常值。优点是结合了回归分析,适用于时间序列数据。缺点是依赖于模型的准确性,适用于线性关系的数据。
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
# 生成线性数据集
np.random.seed(42)
X = np.arange(100)
y = 3 * X + 7 + np.random.normal(0, 10, size=X.shape)
# 添加异常值
X_with_outliers = np.append(X, [20, 50, 80])
y_with_outliers = np.append(y, [1000, -1000, 500])
# 基于回归方法的异常值检测 - 残差分析
def detect_outliers_residual_analysis(X, y):
X = X.reshape(-1, 1)
model = LinearRegression()
model.fit(X, y)
predictions = model.predict(X)
residuals = y - predictions
residual_std = np.std(residuals)
residual_mean = np.mean(residuals)
outliers = np.where(np.abs(residuals) > 3 * residual_std)
return outliers
# 检测数据集中的异常值
outliers_residual = detect_outliers_residual_analysis(X_with_outliers, y_with_outliers)
# 可视化原始数据和异常值
plt.figure(figsize=(10, 6))
plt.scatter(X_with_outliers, y_with_outliers, edgecolor='k', s=20, label='Data')
plt.scatter(X_with_outliers[outliers_residual], y_with_outliers[outliers_residual], color='red', edgecolor='k', s=50, label='Outliers')
plt.plot(X, 3 * X + 7, color='blue', linewidth=2, label='True Function')
plt.title('Residual Analysis Method (with Outliers)')
plt.legend()
plt.show()
【其他方法-主成分分析】
PCA,通过降维,分析主成分,找出在主成分空间中偏离较远的数据点。优点是降维后检测异常值,适用于多维数据。缺点是解释性较差,适用于线性关系的数据。
def detect_outliers_pca(X, n_components=1):
pca = PCA(n_components=n_components)
X_pca = pca.fit_transform(X.reshape(-1, 1))
outliers = detect_outliers_zscore(X_pca)
return outliers
outliers_pca_normal = detect_outliers_pca(X_normal_with_outliers)
outliers_pca_uniform = detect_outliers_pca(X_uniform_with_outliers)
plot_data(X_normal_with_outliers, outliers_pca_normal[0], 'PCA Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_pca_uniform[0], 'PCA Method - 非正态分布+异常值')
【其他方法-高斯混合模型】
GMM,假设数据由多个高斯分布组成,找出概率较低的点。优点是适用于复杂分布的数据。缺点是计算复杂度较高,需选择适当的分布数量。
def detect_outliers_gmm(X, n_components=1):
gmm = GaussianMixture(n_components=n_components, covariance_type='full')
gmm.fit(X.reshape(-1, 1))
scores = gmm.score_samples(X.reshape(-1, 1))
threshold = np.percentile(scores, 5)
outliers = np.where(scores < threshold)
return outliers
outliers_gmm_normal = detect_outliers_gmm(X_normal_with_outliers, n_components=1)
outliers_gmm_uniform = detect_outliers_gmm(X_uniform_with_outliers, n_components=1)
plot_data(X_normal_with_outliers, outliers_gmm_normal[0], 'GMM Method - 正态分布+异常值')
plot_data(X_uniform_with_outliers, outliers_gmm_uniform[0], 'GMM Method - 非正态分布+异常值')
下面是一些建议,根据需要检测数据的维度不同,可以选择不同的检验方法。
一维数据建议:标准差法,箱线图法(IQR法),Z-Score法;
二维数据建议:残差分析,K-最近邻(KNN),局部离群因子(LOF),DBSCAN;
多维数据建议:孤立森林(Isolation Forest),一类支持向量机(One-Class SVM),主成分分析(PCA),高斯混合模型(GMM)。
【异常值处理】
【删除异常值数据】
直接删除检测到的异常值。优点:简单直接,能有效去除异常值。缺点:可能丢失重要信息,尤其在数据量较小的情况下。
def remove_outliers(X, outliers):
return np.delete(X, outliers, axis=0)
X_normal_no_outliers = remove_outliers(X_normal_with_outliers, outliers_gmm_normal)
X_uniform_no_outliers = remove_outliers(X_uniform_with_outliers, outliers_gmm_uniform)
plot_data(X_normal_no_outliers, [], 'Removed Outliers - Normal')
plot_data(X_uniform_no_outliers, [], 'Removed Outliers - Uniform')
【均值/中位数替换】
将异常值替换为数据的均值或中位数。优点:能保持数据规模,对大多数情况适用。缺点:可能掩盖数据的真实波动。
def replace_with_mean(X, outliers):
mean = np.mean(X, axis=0)
X[outliers] = mean
return X
X_normal_mean_replaced = replace_with_mean(X_normal_with_outliers.copy(), outliers_std_normal)
X_uniform_mean_replaced = replace_with_mean(X_uniform_with_outliers.copy(), outliers_std_uniform)
【前/后值替换】
在时间序列数据中,使用前一个或后一个值替换异常值。优点:简单直接,适用于时间序列数据。缺点:可能引入滞后效应,影响数据的真实性。
def replace_with_previous(X, outliers):
for outlier in outliers[0]:
if outlier == 0:
X[outlier] = X[outlier + 1]
else:
X[outlier] = X[outlier - 1]
return X
X_normal_prev_replaced = replace_with_previous(X_normal_with_outliers.copy(), outliers_std_normal)
X_uniform_prev_replaced = replace_with_previous(X_uniform_with_outliers.copy(), outliers_std_uniform)
【插值法】
利用线性插值或其他插值方法替换异常值。优点:能保持数据的连续性和趋势。缺点:对插值方法的选择较为敏感。
def interpolate_outliers(X, outliers):
for outlier in outliers[0]:
if outlier == 0:
X[outlier] = X[outlier + 1]
elif outlier == len(X) - 1:
X[outlier] = X[outlier - 1]
else:
X[outlier] = (X[outlier - 1] + X[outlier + 1]) / 2
return X
X_normal_interpolated = interpolate_outliers(X_normal_with_outliers.copy(), outliers_std_normal)
X_uniform_interpolated = interpolate_outliers(X_uniform_with_outliers.copy(), outliers_std_uniform)
【对数变换】
对数据进行对数变换,可以减小异常值的影响。优点:适用于具有指数分布的数据。缺点:不能处理负值和零值,适用范围有限。
def log_transform(X):
return np.log1p(X) # log1p能处理X中的0值
X_normal_log_transformed = log_transform(X_normal_with_outliers)
X_uniform_log_transformed = log_transform(X_uniform_with_outliers)
【平方根变换】
通过平方根变换减少异常值的影响。优点:适用于具有正偏态分布的数据。缺点:对负值和零值不适用。
def sqrt_transform(X):
return np.sqrt(X)
X_normal_sqrt_transformed = sqrt_transform(X_normal_with_outliers)
X_uniform_sqrt_transformed = sqrt_transform(X_uniform_with_outliers)
【标准化】
将数据缩放到一个标准正态分布。优点:消除量纲影响,适用于多种分析方法。缺点:对非正态分布的数据效果一般。
def standardize(X):
return (X - np.mean(X, axis=0)) / np.std(X, axis=0)
X_normal_standardized = standardize(X_normal_with_outliers)
X_uniform_standardized = standardize(X_uniform_with_outliers)
【归一化】
将数据缩放到[0, 1]的范围内。优点:适用于范围差异较大的数据。缺点:对异常值敏感,可能被极端值影响。
def normalize(X):
min_val = np.min(X, axis=0)
max_val = np.max(X, axis=0)
return (X - min_val) / (max_val - min_val)
X_normal_normalized = normalize(X_normal_with_outliers)
X_uniform_normalized = normalize(X_uniform_with_outliers)
【鲁棒统计量】
使用中位数和四分位数等对异常值不敏感的统计量。优点:对异常值不敏感,适用于非正态分布的数据。缺点:不能完全消除异常值的影响。
def robust_standardize(X):
median = np.median(X, axis=0)
IQR = np.percentile(X, 75, axis=0) - np.percentile(X, 25, axis=0)
return (X - median) / IQR
X_normal_robust_standardized = robust_standardize(X_normal_with_outliers)
X_uniform_robust_standardized = robust_standardize(X_uniform_with_outliers)
通过这些示例,我们可以看到各种异常值处理方法在处理数据异常值时的效果。不同的方法适用于不同类型的数据和场景,选择合适的方法可以有效提高数据分析的准确性和可靠性。
链接是我使用PowerBI整合的历史文章,按类型分类,可以根据需求查询:Microsoft Power BI↓
https://app.powerbi.com/view?r=eyJrIjoiNjI2NWQ3NjktYjU0ZC00ZWZhLTgzMDgtMGI4ZTk1ZDlkODM3IiwidCI6IjI3NDQ3MWQ0LTM4ZDQtNDVlZS1hMmJkLWU1NTVhOTBkYzM4NiJ9
End
- 上一篇: 在用油运动粘度测量
- 下一篇: 【A/B实验常见问题】实验异常值应该如何处理?
猜你喜欢
- 2025-01-21 生成式模型与判别式模型对比
- 2025-01-21 【A/B实验常见问题】实验异常值应该如何处理?
- 2025-01-21 在用油运动粘度测量
- 2025-01-21 基于混合重采样的非平衡数据SVM训练方法
- 2025-01-21 通过高光谱成像高效识别微塑料 上
- 2025-01-21 锂离子电池剩余使用寿命预测方法综述
- 2025-01-21 最重要的机器学习算法
- 2025-01-21 一文解释支持向量机
- 2025-01-21 当支持向量机遇上神经网络:SVM、GAN距离之间的关系
- 2025-01-21 支持向量机(SVM)简介
- 05-16一文学完《图解HTTP》
- 05-16您未被授权查看该页
- 05-16快码住!带你十分钟搞懂HTTP与HTTPS协议及请求的区别
- 05-16一张图带你了解HTTP 9个请求方法,收藏!
- 05-16Java 里的基本类型和引用类型
- 05-16新手小白学Java|零基础入门笔记|原来学Java可以这么简单
- 05-16深度学习CV方向高频算法面试题6道|含解析
- 05-16C语言结构体成员变量名后加冒号和数字的含义
- 最近发表
- 标签列表
-
- newcoder (56)
- 字符串的长度是指 (45)
- drawcontours()参数说明 (60)
- unsignedshortint (59)
- postman并发请求 (47)
- python列表删除 (50)
- 左程云什么水平 (56)
- 计算机网络的拓扑结构是指() (45)
- 编程题 (64)
- postgresql默认端口 (66)
- 数据库的概念模型独立于 (48)
- 产生系统死锁的原因可能是由于 (51)
- 数据库中只存放视图的 (62)
- 在vi中退出不保存的命令是 (53)
- 哪个命令可以将普通用户转换成超级用户 (49)
- noscript标签的作用 (48)
- 联合利华网申 (49)
- swagger和postman (46)
- 结构化程序设计主要强调 (53)
- 172.1 (57)
- apipostwebsocket (47)
- 唯品会后台 (61)
- 简历助手 (56)
- offshow (61)
- mysql数据库面试题 (57)