4.1 数据质量检查与初步探查


4.1 数据质量检查与初步探查

本节摘要:清洗的第一步不是动手改数据,而是给数据做一次全面体检。本节教你用 info、describe 快速扫描结构,用自定义检查函数揪出缺失、重复、异常、类型错乱四类问题,最后产出一份"问题清单"作为清洗的行动地图。

阅读收获

阅读完本节,你应当能够:

  1. 用 info、describe、shape 完成数据的结构体检
  2. 识别缺失值、重复值、异常值、类型错乱四类常见问题
  3. 编写简单的数据质量检查函数并解释输出
  4. 建立"问题清单",按优先级安排清洗顺序

一、问题与直觉

拿到一份新数据的正确姿势是什么?直接开跑分析是大忌——你不知道它缺了多少、有没有重复、金额列里是不是混着字符串。先体检再动手,能避免后面一半的返工。就像看医生,先做全套检查拿到报告,才谈得上治疗。

二、核心原理

2.1 四类常见数据问题

这四类问题往往同时存在,且会互相放大:类型错乱的金额列,统计出来全是错的;带着异常值算均值,直接被大单带偏。体检的意义就是把它们一次性摊开。

2.2 体检工具的分工

  • info():看结构——每列类型、非空数量、内存占用
  • describe():看数值分布——均值、分位、极值,异常值会在 max/min 处露出马脚
  • head()/sample():看样例——格式问题(日期不统一、有多余空格)只能靠肉眼
  • value_counts():看类别——不一致记录("北京"和"北京市")在这现形

三、工程实践要点

3.1 结构体检

import pandas as pd df = pd.read_csv("orders.csv") print(df.shape) # 行数、列数 df.info() # 类型与非空 df.describe() # 数值统计

💡 关键直觉:info() 的"非空计数"是最快的缺失扫描——哪一列的数字明显少于行数,哪列就有缺失。describe() 的 max 异常巨大,多半有异常值。

3.2 编写质量检查函数

def quality_report(df): report = { "行数": df.shape[0], "列数": df.shape[1], "每列缺失数": df.isnull().sum().to_dict(), "重复行数": df.duplicated().sum(), "列类型": df.dtypes.astype(str).to_dict(), } for col in df.columns: report[f"{col} 唯一值数"] = df[col].nunique() return report print(quality_report(df))

一份检查报告输出四类关键信息:规模、缺失、重复、类型。把这些信息对照业务常识,就能圈出可疑列。

3.3 常见问题与识别方法速查

问题 表现 怎么发现
缺失 空值、NaN isnull().sum()
重复 同一订单出现多次 duplicated().sum()
类型错乱 金额列是 object dtypesinfo()
异常值 max 离谱 describe()、箱线图
格式不一 日期、空格、大小写 head()value_counts()
不一致记录 北京 vs 北京市 value_counts() 观察

3.4 贯穿案例:订单表体检

import pandas as pd import numpy as np df = pd.DataFrame({ "订单号": ["A001", "A002", "A002", "A004", None], "金额": [199, 355, 355, 12999, 89], "门店": ["北京", "上海", "上海", "北京市", "广州"], "日期": ["2026-01-01", "2026-01-01", "2026-01-01", "20260102", "2026-01-03"], }) print("缺失:", df.isnull().sum().sum()) print("重复行:", df.duplicated().sum()) print("金额最大值异常:", df["金额"].max()) # 12999 明显离群 print("门店取值:", df["门店"].value_counts().to_dict()) # 北京 与 北京市 不一致 print("日期格式:", df["日期"].tolist()) # 混用两种格式

体检结果一眼可见五个问题:1 个缺失订单号、1 行重复、12999 的异常金额、门店名不一致、日期格式混用。这份清单就是后续四节的行动地图。

⚠️ 常见坑:体检时看到"重复行"不要直接删——先看它是不是业务上合法的重复。比如同一订单号下多件商品,每行一条,订单号重复是正常的,重复的应该是"订单号+商品"组合。

3.5 问题清单的优先级

优先级 问题类型 理由
缺失、类型错乱 影响所有下游计算
重复 成倍放大统计
异常值 影响均值类指标
格式不一 影响分组与匹配
不一致记录 影响展示与聚合

3.6 更细的检查:逐列类型与取值范围

info() 只给整体概览,逐列细查能发现更深的问题:

# 每列类型与缺失 for col in df.columns: print(f"{col}: {df[col].dtype}, 缺失 {df[col].isnull().sum()}, " f"唯一值 {df[col].nunique()}") # 数值列的范围检查 print("金额范围:", df["金额"].min(), "-", df["金额"].max()) print("负值订单数:", (df["金额"] < 0).sum())

"唯一值数"是体检的重要指标:客户 ID 应该基本都不同(唯一值≈行数),门店应该很少(唯一值个位数)。唯一值数明显违背业务直觉的列,就是问题的藏身处

3.7 数据字典:把体检做成标准

团队里数据源不止一个时,值得维护一份"数据字典":每列的名称、含义、类型、取值范围、是否允许缺失。体检时按字典逐项核对,新增字段第一时间更新字典。这样任何数据源变动,几分钟就能定位影响面,而不是对着陌生列猜含义。

3.8 体检的自动化与定期化

把 quality_report 写进管道入口,每次数据更新自动跑一遍:

def quality_gate(df): """数据质量闸门:不达标直接报错,阻止脏数据进入下游。""" report = quality_report(df) assert report["重复行数"] == 0, "存在重复行" assert report["每列缺失数"].get("金额", 0) == 0, "金额列有缺失" print("质量闸门通过") return df

"质量闸门"的思路在工程化中很关键——与其让脏数据一路流到分析结果里才爆雷,不如在入口处拦住它。

要点串联

  • 要点一:先体检再动手,info + describe + head 三件套打底
  • 要点二:四类核心问题——缺失、重复、类型错乱、异常值,用对应方法识别
  • 要点三isnull().sum() 扫缺失、duplicated().sum() 扫重复、describe() 看极值
  • 要点四:写一个 quality_report 函数,把体检自动化、可复用
  • 要点五:重复不等于都要删,先判断业务上是否合法
  • 要点六:问题清单按"影响下游程度"排优先级,先急后缓

体检报告出来了,下一节逐个击破——先处理最普遍的缺失值与重复值。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U