在python中,数据质量的异常检测和完整性检查可通过统计学方法、机器学习算法和pandas等工具实现。1. 异常检测常用z-score和iqr方法,z-score适用于正态分布,iqr适用于偏态分布;2. 机器学习方法如孤立森林、dbscan和one-class svm可用于复杂模式识别;3. 完整性检查包括缺失值检测与处理(如填充或删除)、重复值识别与处理(如去重)、数据类型与格式验证、逻辑一致性检查及唯一性验证。这些步骤通常结合使用,以确保数据质量,支撑后续分析与建模可靠性。

数据质量中的异常检测和完整性检查,在Python里我们通常会结合统计学方法、特定领域知识以及强大的数据处理库(比如Pandas、NumPy),甚至一些机器学习算法来完成。说白了,就是用代码去“审视”数据,看看它是不是“干净”的,有没有“毛病”,比如数值是不是超出了正常范围,有没有重复的记录,或者关键信息是不是缺失了。这个过程是数据分析和建模前非常关键的一步,直接决定了后续工作的可靠性。

要用Python检测数据质量中的异常和进行完整性检查,我们需要一套组合拳。这不仅仅是跑几行代码那么简单,它更像是一种艺术,需要你对数据有深刻的理解,才能判断什么算“异常”,什么才算“完整”。
异常检测:
立即学习“Python免费学习笔记(深入)”;

完整性检查:
NaN
None
这些方法并非孤立存在,很多时候我们需要结合使用。比如,先用统计方法找出初步的异常点,再结合业务经验判断它们是否真的“异常”,或者先处理缺失值和重复值,再进行异常检测。

在Python中,识别数值型数据中的统计异常,最常用的就是Z-score和IQR这两种方法。这两种方法各有侧重,Z-score对正态分布的数据更敏感,而IQR则对偏态分布的数据表现更稳健。
使用Z-score检测异常: Z-score的计算公式是
(数据点 - 均值) / 标准差
import pandas as pd
import numpy as np
# 假设我们有这样一组数据
data = {'value': [10, 12, 11, 13, 100, 14, 15, 9, 8, 10, -50]}
df = pd.DataFrame(data)
# 计算Z-score
df['z_score'] = np.abs((df['value'] - df['value'].mean()) / df['value'].std())
# 设定Z-score阈值,找出异常值
threshold = 3
outliers_zscore = df[df['z_score'] > threshold]
print("基于Z-score的异常值:")
print(outliers_zscore)
# 实际操作中,我们可能还会结合可视化,比如散点图或直方图,来观察这些异常点的位置。这种方法简单直接,但它有个明显的“缺点”:均值和标准差本身就容易受到异常值的影响。也就是说,如果数据中已经存在一些极端的异常值,它们可能会“拉高”均值或标准差,从而使得一些原本应该被识别出来的异常值变得不那么“异常”了。
使用IQR检测异常: IQR是基于四分位数的方法,它对极端值不那么敏感。Q1是25%分位数,Q3是75%分位数,IQR = Q3 - Q1。异常值通常被定义为:
Q1 - 1.5 * IQR
Q3 + 1.5 * IQR
# 继续使用上面的DataFrame df
Q1 = df['value'].quantile(0.25)
Q3 = df['value'].quantile(0.75)
IQR = Q3 - Q1
# 定义异常值的上下界
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
# 找出异常值
outliers_iqr = df[(df['value'] < lower_bound) | (df['value'] > upper_bound)]
print("\n基于IQR的异常值:")
print(outliers_iqr)IQR方法在处理非正态分布或包含极端离群值的数据时更为稳健,因为它不依赖于均值和标准差。在我的经验里,对于大多数真实世界的数据集,IQR往往是更安全、更可靠的初步异常检测方法。
数据完整性是数据质量的基石,而缺失值和重复项是其中最常见也最需要优先处理的问题。Python的Pandas库提供了非常强大和直观的工具来应对这些挑战。
缺失值处理: 缺失值就像数据中的“黑洞”,它们可能是数据采集时的疏忽,也可能是数据本身就不存在。识别和处理它们是第一步。
import pandas as pd
import numpy as np
# 创建一个包含缺失值的示例DataFrame
data = {
    'id': [1, 2, 3, 4, 5],
    'name': ['Alice', 'Bob', np.nan, 'David', 'Eve'],
    'age': [25, 30, 22, np.nan, 28],
    'city': ['NY', 'LA', 'NY', 'LA', np.nan]
}
df_missing = pd.DataFrame(data)
print("原始DataFrame:")
print(df_missing)
# 1. 检测缺失值:
print("\n检测缺失值(True表示缺失):")
print(df_missing.isnull()) # 或者 df_missing.isna()
# 2. 统计每列的缺失值数量:
print("\n每列缺失值数量:")
print(df_missing.isnull().sum())
# 3. 可视化缺失值(通常用heatmap更直观,这里用文字描述):
# import seaborn as sns
# import matplotlib.pyplot as plt
# sns.heatmap(df_missing.isnull(), cbar=False, cmap='viridis')
# plt.show()
# 4. 处理缺失值:
# a. 删除含有缺失值的行:
df_dropna_rows = df_missing.dropna()
print("\n删除含有缺失值的行:")
print(df_dropna_rows)
# b. 删除含有缺失值的列:
df_dropna_cols = df_missing.dropna(axis=1)
print("\n删除含有缺失值的列:")
print(df_dropna_cols)
# c. 填充缺失值:
# 填充固定值
df_fill_fixed = df_missing.fillna('未知')
print("\n填充固定值'未知':")
print(df_fill_fixed)
# 填充数值列的均值
df_fill_mean = df_missing.copy()
df_fill_mean['age'].fillna(df_fill_mean['age'].mean(), inplace=True)
print("\n填充age列的均值:")
print(df_fill_mean)
# 填充类别列的众数
df_fill_mode = df_missing.copy()
df_fill_mode['city'].fillna(df_fill_mode['city'].mode()[0], inplace=True)
print("\n填充city列的众数:")
print(df_fill_mode)
# 前向填充(ffill)或后向填充(bfill)
df_ffill = df_missing.fillna(method='ffill')
print("\n前向填充:")
print(df_ffill)选择哪种处理方式,很大程度上取决于数据的特性和业务场景。删除行是最简单粗暴的,但可能损失大量信息;填充则需要谨慎,不当的填充可能会引入偏差。
重复项处理: 重复项是指数据集中存在完全相同或在特定标识符上重复的记录。它们可能导致统计结果偏差,甚至影响模型训练的准确性。
# 创建一个包含重复项的示例DataFrame
data_dup = {
    'id': [1, 2, 3, 2, 4, 1],
    'name': ['Alice', 'Bob', 'Charlie', 'Bob', 'David', 'Alice'],
    'age': [25, 30, 22, 30, 28, 25],
    'city': ['NY', 'LA', 'NY', 'LA', 'SF', 'NY']
}
df_duplicates = pd.DataFrame(data_dup)
print("\n原始DataFrame(含重复项):")
print(df_duplicates)
# 1. 检测重复项:
# 默认检测所有列都重复的行
print("\n检测所有列都重复的行:")
print(df_duplicates.duplicated())
# 统计重复行的数量
print("\n重复行的数量:", df_duplicates.duplicated().sum())
# 检测特定列(如'id'和'name')重复的行
print("\n检测id和name列重复的行:")
print(df_duplicates.duplicated(subset=['id', 'name']))
# 2. 处理重复项:
# 删除重复行,默认保留第一次出现的记录
df_no_duplicates = df_duplicates.drop_duplicates()
print("\n删除重复行(保留第一次出现):")
print(df_no_duplicates)
# 删除重复行,保留最后一次出现的记录
df_no_duplicates_last = df_duplicates.drop_duplicates(keep='last')
print("\n删除重复行(保留最后一次出现):")
print(df_no_duplicates_last)
# 删除重复行,基于特定列(如'id')
df_no_duplicates_subset = df_duplicates.drop_duplicates(subset=['id'])
print("\n删除基于id列的重复行:")
print(df_no_duplicates_subset)处理重复项时,
keep
除了传统的统计学方法,Python在机器学习领域也提供了多种强大的工具,可以帮助我们发现数据中那些更复杂、更“怪异”的异常模式。这些方法通常不依赖于数据是否服从某种特定分布,而是尝试学习数据的内在结构,从而识别出偏离常规的“异类”。
1. 孤立森林 (Isolation Forest): 这是我个人在实际项目中非常喜欢用的一种算法,因为它既高效又有效。孤立森林的基本思想是,异常点是“少数派”,并且它们在数据空间中通常距离其他正常点更远,更容易被“孤立”出来。算法通过随机选择特征并随机选择分割点来构建决策树,异常点往往在更少的分割步骤中就被分到叶子节点。
from sklearn.ensemble import IsolationForest
import pandas as pd
import numpy as np
# 构造一个包含正常点和少量异常点的数据集
X = np.array([
    [1, 1], [1.2, 1.1], [1.1, 1.2], [1.3, 1.3], [1.0, 1.0],
    [10, 10], # 异常点1
    [1.5, 1.6], [1.4, 1.5], [1.6, 1.4],
    [-5, -5]  # 异常点2
])
df_ml = pd.DataFrame(X, columns=['feature1', 'feature2'])
# 初始化Isolation Forest模型
# contamination参数表示数据集中异常值的比例,这是一个先验知识,也可以不设置让模型自己学习
# random_state用于保证结果可复现
model = IsolationForest(contamination=0.1, random_state=42)
# 训练模型(实际上,Isolation Forest是无监督的,fit方法只是学习数据分布)
model.fit(df_ml)
# 预测每个点的异常分数(越低越异常)和标签(-1表示异常,1表示正常)
df_ml['anomaly_score'] = model.decision_function(df_ml)
df_ml['is_anomaly'] = model.predict(df_ml)
print("Isolation Forest检测结果:")
print(df_ml)
# 筛选出被标记为异常的点
outliers_if = df_ml[df_ml['is_anomaly'] == -1]
print("\nIsolation Forest识别出的异常点:")
print(outliers_if)孤立森林的优势在于它不需要对数据分布做任何假设,并且对高维数据也能有不错的表现。它的输出是一个异常分数,这允许我们根据业务需求调整异常的“严格程度”。
2. DBSCAN (Density-Based Spatial Clustering of Applications with Noise): DBSCAN是一种基于密度的聚类算法。它将数据点分为三类:核心点、边界点和噪声点。噪声点就是那些不属于任何密集区域的点,它们通常被视为异常值。DBSCAN不需要预设聚类数量,这在异常检测中非常有用。
from sklearn.cluster import DBSCAN
import pandas as pd
import numpy as np
# 构造数据,包含一些密集区域和一些稀疏的噪声点
X_dbscan = np.array([
    [1, 1], [1.2, 1.1], [1.1, 1.2], # 簇1
    [5, 5], [5.1, 5.2], [5.3, 5.1], # 簇2
    [10, 10], # 噪声点1
    [0, 0],   # 噪声点2
    [1.5, 1.6], [1.4, 1.5] # 簇1
])
df_dbscan = pd.DataFrame(X_dbscan, columns=['x', 'y'])
# 初始化DBSCAN模型
# eps: 邻域半径,min_samples: 形成核心点所需的最小样本数
dbscan = DBSCAN(eps=0.7, min_samples=2)
# 训练并预测
clusters = dbscan.fit_predict(df_dbscan)
df_dbscan['cluster'] = clusters
print("\nDBSCAN聚类结果(-1表示噪声/异常):")
print(df_dbscan)
# 筛选出被标记为噪声(异常)的点
outliers_dbscan = df_dbscan[df_dbscan['cluster'] == -1]
print("\nDBSCAN识别出的异常点:")
print(outliers_dbscan)DBSCAN的挑战在于选择合适的
eps
min_samples
3. One-Class SVM (One-Class Support Vector Machine): One-Class SVM主要用于“异常检测”,它学习一个决策函数,将数据点分为一类(正常点)和另一类(异常点)。它通过找到一个超平面,将大部分数据点(正常点)包围起来,而将远离这个超平面的点视为异常。
from sklearn.svm import OneClassSVM
import pandas as pd
import numpy as np
# 构造数据,大部分是正常点,少量异常点
X_ocsvm = np.array([
    [0.1, 0.1], [0.2, 0.2], [0.3, 0.3], [0.4, 0.4], [0.5, 0.5],
    [10, 10], # 异常点
    [0.15, 0.15], [0.25, 0.25],
    [-5, -5] # 异常点
])
df_ocsvm = pd.DataFrame(X_ocsvm, columns=['f1', 'f2'])
# 初始化One-Class SVM模型
# nu参数表示异常值的比例(通常是0到1之间),类似于Isolation Forest的contamination
ocsvm = OneClassSVM(nu=0.1, kernel="rbf", gamma='auto')
# 训练模型
ocsvm.fit(df_ocsvm)
# 预测每个点的标签(-1表示异常,1表示正常)
df_ocsvm['is_anomaly'] = ocsvm.predict(df_ocsvm)
print("\nOne-Class SVM检测结果:")
print(df_ocsvm)
# 筛选出被标记为异常的点
outliers_ocsvm = df_ocsvm[df_ocsvm['is_anomaly'] == -1]
print("\nOne-Class SVM识别出的异常点:")
print(outliers_ocsvm)One-Class SVM在处理高维数据和复杂模式时表现良好,但它的计算成本相对较高,并且对
nu
选择哪种高级技术,取决于你的数据特性、异常的定义以及计算资源。有时候,这些方法会比简单的统计方法更能发现那些“隐藏”在数据深处的、不易察觉的“怪异”模式。但话说回来,任何算法都只是工具,最终的判断还是得结合我们对业务的理解。
以上就是Python怎样检测数据质量中的异常?完整性检查的详细内容,更多请关注php中文网其它相关文章!
 
                        
                        每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
 
                Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号