百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

数据异常值检测方法汇总and异常值处理

ztj100 2025-01-05 01:00 19 浏览 0 评论

昨天介绍了数据的标准化处理方法《数据标准化(归一化)》,里面介绍了常见的方法。而且数据里面有异常值的情况下不同方法的作用性也不一样。今天就来详细介绍一下数据异常值的检测方法,以及如何处理异常值。

异常值检测与处理是数据清洗过程中的一个关键步骤,它涉及到识别和处理那些与大多数数据显著不同的数据点。异常值可能是由于数据录入错误、测量误差、数据损坏或其他原因造成的。处理异常值的目的是提高数据的质量,避免它们对分析结果产生不利影响。以下是异常值检测与处理的详细介绍。

【异常值检测】

整体分成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

相关推荐

这个 JavaScript Api 已被废弃!请慎用!

在开发过程中,我们可能会不自觉地使用一些已经被标记为废弃的JavaScriptAPI。这些...

JavaScript中10个“过时”的API,你的代码里还在用吗?

JavaScript作为一门不断发展的语言,其API也在持续进化。新的、更安全、更高效的API不断涌现,而一些旧的API则因为各种原因(如安全问题、性能瓶颈、设计缺陷或有了更好的替代品)被标记为“废...

几大开源免费的 JavaScript 富文本编辑器测评

MarkDown编辑器用的时间长了,发现发现富文本编辑器用起来是真的舒服。...

比较好的网页里面的 html 编辑器 推荐

如果您正在寻找嵌入到网页中的HTML编辑器,以便用户可以直接在网页上编辑HTML内容,以下是几个备受推荐的:CKEditor:CKEditor是一个功能强大的、开源的富文本编辑器,可以嵌入到...

Luckysheet 实现excel多人在线协同编辑

前言前些天看到Luckysheet支持协同编辑Excel,正符合我们协同项目的一部分,故而想进一步完善协同文章,但是遇到了一下困难,特此做声明哈,若侵权,请联系我删除文章!若侵犯版权、个人隐私,请联系...

从 Element UI 源码的构建流程来看前端 UI 库设计

作者:前端森林转发链接:https://mp.weixin.qq.com/s/ziDMLDJcvx07aM6xoEyWHQ引言...

手把手教你如何用 Decorator 装饰你的 Typescript?「实践」

作者:Nealyang转发连接:https://mp.weixin.qq.com/s/PFgc8xD7gT40-9qXNTpk7A...

推荐五个优秀的富文本编辑器

富文本编辑器是一种可嵌入浏览器网页中,所见即所得的文本编辑器。对于许多从事前端开发的小伙伴来说并不算陌生,它的应用场景非常广泛,平时发个评论、写篇博客文章等都能见到它的身影。...

基于vue + element的后台管理系统解决方案

作者:林鑫转发链接:https://github.com/lin-xin前言该方案作为一套多功能的后台框架模板,适用于绝大部分的后台管理系统(WebManagementSystem)开发。基于v...

开源富文本编辑器Quill 2.0重磅发布

开源富文本编辑器Quill正式发布2.0版本。官方TypeScript声明...

Python之Web开发框架学习 Django-表单处理

在Django中创建表单实际上类似于创建模型。同样,我们只需要从Django类继承,则类属性将是表单字段。让我们在myapp文件夹中添加一个forms.py文件以包含我们的应用程序表单。我们将创建一个...

Django测试入门:打造坚实代码基础的钥匙

这一篇说一下django框架的自动化测试,...

Django ORM vs SQLAlchemy:到底谁更香?从入门到上头的选择指南

阅读文章前辛苦您点下“关注”,方便讨论和分享,为了回馈您的支持,我将每日更新优质内容。...

超详细的Django 框架介绍,它来了!

时光荏苒,一晃小编的Tornado框架系列也结束了。这个框架虽然没有之前的FastAPI高流量,但是,它也是小编的心血呀。总共16篇博文,从入门到进阶,包含了框架的方方面面。虽然小编有些方面介绍得不是...

20《Nginx 入门教程》使用 Nginx 部署 Python 项目

今天的目标是完成一个PythonWeb项目的线上部署,我们使用最新的Django项目搭建一个简易的Web工程,然后基于Nginx服务部署该PythonWeb项目。1.前期准备...

取消回复欢迎 发表评论: