查看: 101|回复: 1

Python脚本实现Excel数据质量自动检测:重复、缺失与逻辑错误标记

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
在日常数据处理工作中,从Excel中人工检查几千行数据的重复项、缺失值和逻辑错误不仅耗时,而且容易遗漏。借助Python的pandas和openpyxl库,我们可以编写一个可复用的数据质量检测脚本,自动标记问题行并输出质检报告。

## 检测原理

数据质量检测主要基于三类检查:
- 重复检测:通过 pandas 的 duplicated() 方法识别完全重复或关键字段重复的行。
- 缺失检测:利用 isna() 或 isnull() 找出空值、空字符串等缺失情况。
- 逻辑检测:根据业务规则(如金额≥0、年龄18-65等)使用布尔条件过滤异常值。

整个流程:读取原始数据 → 重复检测 → 缺失检测 → 逻辑检测 → 生成报告(包含问题数据表和高亮标记)。

## 环境准备

运行以下命令安装依赖:
  1. pip install pandas openpyxl
复制代码

## 完整代码实现

以下是一个自定义函数 data_quality_check,它接收输入文件、必填字段列表和自定义规则字典,输出检测报告和问题数据文件。
  1. import pandas as pd
  2. import numpy as np
  3. from openpyxl import load_workbook
  4. from openpyxl.styles import PatternFill
  5. def data_quality_check(input_file, required_columns=None, rules=None, output_file="数据质检报告.xlsx"):
  6.     """
  7.     对 Excel 数据进行质量检查,输出检测报告
  8.     参数:
  9.         input_file: 待检查的 Excel 文件
  10.         required_columns: 必填字段列表
  11.         rules: 自定义规则字典,如 {'金额': '>=0', '年龄': '18-65'}
  12.         output_file: 输出报告文件名
  13.     """
  14.     df = pd.read_excel(input_file, engine='openpyxl')
  15.     print(f"总数据: {len(df)} 行 × {len(df.columns)} 列\n")
  16.     # ==================== 1. 重复项检测 ====================
  17.     print("=" * 50)
  18.     print("【1. 重复项检测】")
  19.     duplicate_mask = df.duplicated(keep='first')
  20.     duplicate_count = duplicate_mask.sum()
  21.     print(f"完全重复行: {duplicate_count} 行")
  22.     if duplicate_count > 0:
  23.         df['是否重复'] = duplicate_mask
  24.     # ==================== 2. 缺失值检测 ====================
  25.     print("\n【2. 缺失值检测】")
  26.     missing_report = df.isnull().sum()
  27.     missing_report = missing_report[missing_report > 0]
  28.     if len(missing_report) > 0:
  29.         for col, count in missing_report.items():
  30.             pct = count / len(df) * 100
  31.             print(f"  {col}: {count} 个缺失 ({pct:.1f}%)")
  32.     else:
  33.         print("  无缺失值 √")
  34.     if required_columns:
  35.         for col in required_columns:
  36.             if col in df.columns:
  37.                 missing = df[col].isna().sum()
  38.                 blank = (df[col].astype(str).str.strip() == '').sum()
  39.                 total_issues = missing + blank
  40.                 if total_issues > 0:
  41.                     print(f"  ⚠ 必填字段 '{col}' 有 {total_issues} 个空值!")
  42.                     df[f'{col}_必填缺失'] = df[col].isna() | (df[col].astype(str).str.strip() == '')
  43.     # ==================== 3. 逻辑错误检测 ====================
  44.     print("\n【3. 逻辑错误检测】")
  45.     if rules:
  46.         for col, rule in rules.items():
  47.             if col not in df.columns:
  48.                 print(f"  跳过: 列 '{col}' 不存在")
  49.                 continue
  50.             try:
  51.                 if rule.startswith('>='):
  52.                     threshold = float(rule[2:])
  53.                     mask = df[col] < threshold
  54.                     df[f'{col}_逻辑异常'] = mask
  55.                     count = mask.sum()
  56.                     print(f"  {col} < {threshold}: {count} 行异常")
  57.                 elif rule.startswith('<='):
  58.                     threshold = float(rule[2:])
  59.                     mask = df[col] > threshold
  60.                     df[f'{col}_逻辑异常'] = mask
  61.                     count = mask.sum()
  62.                     print(f"  {col} > {threshold}: {count} 行异常")
  63.                 elif '-' in rule:
  64.                     min_val, max_val = rule.split('-')
  65.                     min_val, max_val = float(min_val), float(max_val)
  66.                     mask = (df[col] < min_val) | (df[col] > max_val)
  67.                     df[f'{col}_逻辑异常'] = mask
  68.                     count = mask.sum()
  69.                     print(f"  {col} 不在 [{min_val}-{max_val}]: {count} 行异常")
  70.                 elif rule == '>0':
  71.                     mask = df[col] <= 0
  72.                     df[f'{col}_逻辑异常'] = mask
  73.                     count = mask.sum()
  74.                     print(f"  {col} <= 0: {count} 行异常")
  75.             except Exception as e:
  76.                 print(f"  规则执行失败 {col}: {e}")
  77.     # ==================== 4. 生成报告 ====================
  78.     print("\n" + "=" * 50)
  79.     print("【4. 生成质检报告】")
  80.     flag_columns = [col for col in df.columns if col.endswith(('_重复', '_缺失', '_必填缺失', '_逻辑异常'))]
  81.     if flag_columns:
  82.         df['是否有问题'] = df[flag_columns].any(axis=1)
  83.         issue_count = df['是否有问题'].sum()
  84.         print(f"问题行总数: {issue_count} / {len(df)} ({issue_count/len(df)*100:.1f}%)")
  85.         issue_df = df[df['是否有问题'] == True]
  86.         clean_df = df[df['是否有问题'] == False]
  87.         issue_df.drop(columns=['是否有问题'] + flag_columns, inplace=True, errors='ignore')
  88.         issue_df.to_excel(output_file.replace('.xlsx', '_问题数据.xlsx'), index=False, engine='openpyxl')
  89.         print(f"问题数据已保存: {output_file.replace('.xlsx', '_问题数据.xlsx')}")
  90.         df.to_excel(output_file, index=False, engine='openpyxl')
  91.         print(f"完整报告已保存: {output_file}")
  92.     return df
  93. # ==================== 使用示例 ====================
  94. if __name__ == "__main__":
  95.     data_quality_check(
  96.         input_file="销售数据表.xlsx",
  97.         required_columns=["工号", "姓名", "部门", "金额"],
  98.         rules={
  99.             "金额": ">=0",
  100.             "数量": ">0",
  101.             "年龄": "18-65",
  102.             "折扣率": "0-1",
  103.         },
  104.         output_file="数据质检报告.xlsx"
  105.     )
复制代码

## 进阶技巧

### 技巧1:在Excel中用颜色高亮问题行

利用 openpyxl 给问题行添加红色背景,方便直接查看。
  1. def highlight_issues(excel_file):
  2.     """用红色背景高亮有问题的行"""
  3.     wb = load_workbook(excel_file)
  4.     ws = wb.active
  5.     red_fill = PatternFill(start_color='FFC7CE', fill_type='solid')
  6.     issue_col = 'N'  # 假设'是否有问题'列在第N列
  7.     for row in range(2, ws.max_row + 1):
  8.         if ws[f'{issue_col}{row}'].value == True:
  9.             for cell in ws[row]:
  10.                 cell.fill = red_fill
  11.     wb.save(excel_file)
复制代码

### 技巧2:自动计算数据质量评分

通过缺失比例和重复比例计算一个0-100的质量分数:
  1. total_cells = len(df) * len(df.columns)
  2. missing_cells = df.isnull().sum().sum()
  3. duplicate_rows = df.duplicated().sum()
  4. quality_score = 100 - (missing_cells / total_cells * 50) - (duplicate_rows / len(df) * 50)
  5. print(f"数据质量评分: {quality_score:.1f} / 100")
复制代码

### 技巧3:基于3σ原则检测异常值

对于数值列,可以使用统计学方法自动识别离群点:
  1. def detect_outliers(df, column):
  2.     """检测数值列的异常值(3σ 原则)"""
  3.     mean = df[column].mean()
  4.     std = df[column].std()
  5.     lower = mean - 3 * std
  6.     upper = mean + 3 * std
  7.     outliers = df[(df[column] < lower) | (df[column] > upper)]
  8.     print(f"{column} 异常值: {len(outliers)} 行 (范围: {lower:.2f} ~ {upper:.2f})")
  9.     return outliers
复制代码

## 常见问题与处理

### Q1:日期列缺失检测不到?
如果Excel中日期实际存储为空字符串或0,pandas不会自动视为NaN。解决方法是提前统一替换:
  1. df['日期'] = df['日期'].replace('', pd.NaT)
  2. missing = df['日期'].isna().sum()
复制代码

### Q2:数值列中混入了文本?
使用 pd.to_numeric 将列强制转换为数值,无法转换的会变成NaN,从而可以统计异常:
  1. df['金额'] = pd.to_numeric(df['金额'], errors='coerce')
  2. print(f"非数值单元格: {df['金额'].isna().sum()}")
复制代码

### Q3:如何处理大小写不一致?
统一转为大写并去除空格,比如“北京”与“beijing”视为不同,但可统一格式:
  1. df['城市'] = df['城市'].str.upper().str.strip()
复制代码

## 总结

本文实现了一个通用的Excel数据质量自动检查脚本,覆盖了重复、缺失、逻辑三类核心检测,并提供了高亮行、质量评分、异常值检测等增强功能。这段代码可以直接集成到数据处理流水线中,作为数据清洗的前置步骤,显著提升质检效率与准确性。
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层

Re: Python脚本实现Excel数据质量自动检测:重复、缺失与逻辑错误标记

感谢楼主分享这么实用的脚本!手动检查Excel数据确实是苦力活,这个自动化方案能节省大量时间。我特别关注逻辑检测部分,因为工作中经常遇到类似年龄范围、金额区间这类条件。想请教一下:如果规则像“年龄18-65”这种区间判断,代码示例里只处理了 `>=` 和 `
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-6-22 12:17 , Processed in 0.031308 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部