数据清理(Data Cleaning)
概述
本技能通过 scripts/clean_data.py 对 CSV / TSV / Excel / JSON / JSONL / Parquet 表格数据执行通用清洗流程,并自动生成清洗报告。适用于一次性、批量或重复性的表格数据清洗需求。
使用流程
- 确认用户提供的输入文件格式(CSV / TSV / Excel / JSON / JSONL / Parquet),如缺失则向用户索要文件路径。
- 确认清洗需求,从以下操作中组合出命令行参数(可多选)。
- 使用 managed Python 运行脚本(见下方"运行环境"),传入文件路径与所选参数。
- 将结果文件路径与清洗报告要点反馈给用户。
支持的文件格式
| 格式 | 扩展名 | 读取 | 写入 | |------|--------|------|------| | CSV | .csv | 是 | 是 | | TSV | .tsv | 是 | 是 | | Excel | .xlsx, .xls | 是 | 是(输出 .xlsx) | | JSON | .json | 是 | 是(records 格式) | | JSONL | .jsonl | 是 | 是(每行一个 JSON 对象) | | Parquet | .parquet | 是(需 pyarrow) | 是(需 pyarrow) |
格式通过文件扩展名自动识别。可用 --output-format csv|tsv|json|jsonl|parquet|xlsx 指定输出格式(默认跟随输入)。
支持的操作(命令行参数)
去重
| 需求 | 参数 | 示例 |
|------|------|------|
| 完全去重 | --dedup | 删除所有列完全相同的行 |
| 按列去重 | --dedup-subset 列1,列2 | 保留每个 姓名+电话 组合的第一行 |
| 合并去重 | --dedup-subset 列1,列2 + --dedup-merge | 按业务字段分组合并:组内逐字段优先取非空值 |
缺失值处理
| 需求 | 参数 | 示例 |
|------|------|------|
| 删除缺失行 | --drop-missing 列1,列2 | 删除指定列含空值的行;传 all/全部 或省略则检查所有列 |
| 标记缺失值 | --mark-missing | 数值列缺失->NaN,文本列缺失->空字符串 |
| 指定值填充 | --fill-missing 值 | 全部空值填 "0" |
| 智能填充 | --fill-missing-num | 数值列填中位数,文本列填最高频值;--no-fill-cols 列 排除指定列 |
| 核心字段校验 | --required-cols 列1,列2 + --required-action drop/nan | 核心字段缺失时:drop=删除该行(默认),nan=标记为NaN |
| 分类字段保护 | --category-cols 列1,列2 | 业务类别字段缺失置 NULL 且不参与智能填充 |
格式标准化
| 需求 | 参数 | 示例 |
|------|------|------|
| 去除空白 | --strip | 去掉字符串列首尾空格 |
| 合并连续空白 | --collapse-spaces | 字符串列内部连续空白合并为单个空格 |
| 转小写/大写 | --lower 列 / --upper 列 | 统一文本大小写 |
| 日期标准化 | --date-cols 列1,列2 | 统一为 YYYY-MM-DD,自动识别 Unix 秒/毫秒时间戳 |
| 数值转换 | --numeric-cols 列1 | 文本数字转数值,非法值转 NaN |
| 千分位解析 | --numeric-cols 列1 + --parse-thousands | 数值转换时去除千分位逗号 |
| 连字符规范化 | --normalize-hyphens | 特殊连字符统一为 ASCII - |
列/行操作
| 需求 | 参数 | 示例 |
|------|------|------|
| 删除空列 | --trim-cols 列1 | 删除内容全为空的列 |
| 删除列 | --drop-cols 列1,列2 | 删除不需要的列 |
| 删除行 | --drop-rows 行号1,行号2 | 删除指定行(从1开始计数) |
| 重命名列 | --rename 旧:新,旧2:新2 | 重命名列 |
| 缺失占位符 | --nan-symbol 符号 | 输出文件中缺失值写为可见占位符(默认 NULL) |
异常值检测与处理
| 需求 | 参数 | 示例 |
|------|------|------|
| 异常值检测 | --outliers-cols 列1 | IQR 法检测数值异常值,写入报告 |
| 异常值处理 | --outliers-cols 列1 + --outliers-action drop/winsorize/mark | drop=删除含异常值的行,winsorize=截断到边界,mark=替换为NaN |
数值归一化
| 需求 | 参数 | 示例 |
|------|------|------|
| 归一化 | --normalize minmax/zscore/robust | 数值列标准化,可用 --norm-cols 列1,列2 指定列 |
业务规则引擎
--rules 用 JSON 文件定义业务约束:
{
"salary": {"min": 0},
"age": {"min": 16, "max": 70},
"gender": {"in": ["M", "F"]},
"city": {"not_in": ["unknown"]},
"salary2": ">0"
}
--rules-action drop(默认):删除违规行--rules-action mark:仅把违规值标记为 NaN
新增功能
数据画像分析
--profile 在清洗前自动生成数据画像报告,包括:
- 数据规模、内存占用、重复行统计
- 逐字段画像:推断类型、非空数、缺失率、唯一值数、示例值
- 数值列统计:min/max/mean/median/std/Q1/Q3
- 分类列高频值 Top 5
python clean_data.py data.csv --profile
画像报告默认输出为 data_profile.md,可用 --profile-out 自定义路径。
字段格式校验
--validate 对常见字段执行格式校验,支持以下类型:
| 类型 | 说明 | 校验规则 |
|------|------|---------|
| phone | 中国手机号 | 1[3-9] 开头 + 9位数字 |
| email | 电子邮箱 | 标准邮箱正则 |
| idcard | 中国身份证号 | 18位 + 校验位验证 |
| zip | 邮政编码 | 6位数字 |
| ip | IPv4 地址 | x.x.x.x 格式 |
| url | URL | http/https 开头 |
格式:--validate type:col1,col2,可多次指定不同类型:
python clean_data.py 客户.csv --validate phone:手机号 --validate email:邮箱 --validate-action drop
--validate-action:
report(默认):仅报告违规,不修改数据drop:删除含违规值的行mark:将违规值标记为 NaN
身份证校验包含校验位验证,能检测出末位错误的身份证号。
字符串模式清洗
正则替换 --replace
格式:col:pattern:replacement(多组用 ; 分隔,冒号需转义为 \:)
# 将"北京市"替换为"北京"
python clean_data.py data.csv --replace 城市:北京市:北京
# 多列替换
python clean_data.py data.csv --replace 城市:北京市:北京;备注:NULL:未知
正则提取 --extract
格式:col:pattern:newcol(多组用 ; 分隔)
# 从"张三(12345)"中提取编号到新列
python clean_data.py data.csv --extract 姓名:\((\d+)\):工号
列拆分/合并
列拆分 --split-col
格式:col:sep:newcol1,newcol2(多组用 ; 分隔)
# 将"2024-01-15"拆分为年、月、日
python clean_data.py data.csv --split-col 日期:-:年,月,日
# 将"张三 男"拆分为姓名和性别
python clean_data.py data.csv --split-col "姓名性别: :姓名,性别"
列合并 --merge-cols
格式:newcol:col1+col2:sep(多组用 ; 分隔)
# 将姓和名合并为全名
python clean_data.py data.csv --merge-cols 全名:姓+名:""
# 将省和市合并为地址,用空格分隔
python clean_data.py data.csv --merge-cols 地址:省+市:
PII 脱敏
--mask 对敏感信息进行脱敏处理,支持以下类型:
| 类型 | 说明 | 脱敏规则 | 示例 |
|------|------|---------|------|
| phone | 手机号 | 保留前3后4,中间4位打码 | 13812345678 -> 1385678 |
| idcard | 身份证号 | 保留前6后4,中间8位打码 | 110101199001011234 -> 110101********1234 |
| name | 姓名 | 2字->首字+,3字->首++尾,4字+->首++尾 | 张三->张*, 张小明->张明 |
| email | 邮箱 | 本地部分仅保留首字符+** | zhangsan@qq.com -> z***@qq.com |
| bankcard | 银行卡号 | 保留前6后4,中间打码 | 6222021234567890 -> 622202******7890 |
格式:--mask type:col1,col2,可多次指定:
python clean_data.py 客户.csv --mask phone:手机号 --mask idcard:身份证号 --mask name:姓名
脱敏在所有清洗操作之后、输出之前执行,确保脱敏结果不被后续操作干扰。
批量处理
--batch 对指定目录下所有支持格式的文件批量执行清洗:
# 清洗 data/ 目录下所有文件
python clean_data.py data/ --batch --dedup --strip --fill-missing-num
# 只处理 CSV 文件
python clean_data.py data/ --batch --batch-pattern "*.csv" --dedup --strip
- 自动跳过已清洗的输出文件(含
_cleaned后缀) - 每个文件独立生成清洗结果和报告
- 处理完成后输出批量汇总(成功数、总行数变化)
--batch-pattern支持通配符过滤文件名
运行环境
脚本依赖 pandas 与 openpyxl。使用隔离的 managed venv 运行:
"C:\Users\回彭远\.workbuddy\binaries\python\envs\default\Scripts\python.exe" \
"C:\Users\回彭远\.workbuddy\skills\data-cleaning\scripts\clean_data.py" \
<输入文件或目录> [选项]
若 venv 不存在或缺少依赖,先执行:
"C:\Users\回彭远\.workbuddy\binaries\python\versions\3.13.12\python.exe" -m venv "C:\Users\回彭远\.workbuddy\binaries\python\envs\default"
"C:\Users\回彭远\.workbuddy\binaries\python\envs\default\Scripts\python.exe" -m pip install pandas openpyxl
Parquet 格式需额外安装 pyarrow:
"C:\Users\回彭远\.workbuddy\binaries\python\envs\default\Scripts\python.exe" -m pip install pyarrow
输出
- 清洗后的数据文件:默认在输入文件同目录,文件名加
_cleaned后缀(可用--out指定)。 - 清洗报告:Markdown 格式,默认与输出文件同名加
_report.md(可用--report指定)。 - 数据画像报告(
--profile):Markdown 格式,默认输入文件名_profile.md(可用--profile-out指定)。 - 脚本末尾输出
CLEAN_SUMMARY_JSON:前缀的 JSON 摘要(行数、列数、异常值统计),供解析使用。 - 批量处理时输出包含所有文件汇总的 JSON 摘要。
操作执行顺序
操作顺序固定为:
- 数据画像(
--profile) - 核心字段校验(
--required-cols) - 连字符规范化(
--normalize-hyphens) - 数值转换(
--numeric-cols) - 字段格式校验(
--validate) - 业务规则校验(
--rules) - 缺失值处理(mark/drop/fill)
- 格式标准化(strip/lower/日期/collapse-spaces)
- 字符串模式清洗(
--replace/--extract) - 列拆分/合并(
--split-col/--merge-cols) - 列/行操作(trim/drop/rename)
- 去重(dedup)
- 异常值检测(IQR)
- 空串转缺失
- PII 脱敏(
--mask) - 数值归一化(
--normalize)
示例
示例 1:去重 + 填充缺失值 + 日期标准化
python clean_data.py 客户数据.csv --dedup --fill-missing-num --date-cols 注册日期
示例 2:按列去重 + 去除空白 + 异常值检测
python clean_data.py 销售记录.xlsx --dedup-subset 订单号 --strip --outliers-cols 金额
示例 3:字段校验 + 脱敏 + 画像
python clean_data.py 客户.csv --profile --validate phone:手机 --validate email:邮箱 --validate-action drop --mask phone:手机 --mask name:姓名 --mask idcard:身份证号
示例 4:正则替换 + 列拆分
python clean_data.py data.csv --replace 城市:北京市:北京 --split-col 日期:-:年,月,日
示例 5:批量处理目录
python clean_data.py data/ --batch --batch-pattern "*.csv" --dedup --strip --fill-missing-num
示例 6:JSON 输入 + CSV 输出
python clean_data.py data.json --dedup --strip --output-format csv --out data_cleaned.csv
示例 7:机器学习前处理(转数值 + 归一化)
python clean_data.py data.csv --numeric-cols 年龄,金额 --normalize minmax --norm-cols 年龄,金额
示例 8:核心字段校验 + 业务规则
python clean_data.py 员工.csv --required-cols 姓名 --required-action drop --rules rules.json --rules-action drop
缺失值处理策略
缺失值有四种可选策略,按需组合:
| 策略 | 参数 | 效果 |
|------|------|------|
| 删除行 | --drop-missing 列1,列2 | 删除指定列含缺失的行(all=所有列) |
| 标记 | --mark-missing | 数值列->NaN,文本列->空串,保留原行 |
| 指定值填充 | --fill-missing 值 | 全部缺失填固定值 |
| 智能填充 | --fill-missing-num | 数值->中位数,文本->最高频值;--no-fill-cols 排除列 |
核心字段校验(--required-cols):用于姓名、订单号等不允许为空的关键字段。
--required-action drop:缺失即删除该行(默认)--required-action nan:缺失保留行,标记为 NaN
缺失可见性:输出文件缺失值统一以 NULL 标记(--nan-symbol,默认即 NULL),禁止输出空白。空字符串在输出前统一转为缺失,与 NaN 同等处理。
分类字段保护(--category-cols):部门、职位等业务类别字段缺失时置为 NULL,不参与智能填充。
注意事项
- 脚本不会修改原文件,输出均为新文件,安全可回滚。
- 字段格式校验在数值转换之后、业务规则之前执行,确保数值列已正确转换。
- PII 脱敏在所有清洗操作之后执行,确保脱敏结果不被后续操作干扰。
- 批量处理自动跳过已清洗的输出文件,避免重复处理。
- 列拆分/合并中的分隔符支持任意字符串(包括空字符串、空格等)。
- 正则替换/提取使用 Python re 模块语法,多组规则用
;分隔。 - 身份证校验包含校验位验证,能检测出末位错误的身份证号。
- 中文列名完全支持。
- 智能填充的数值列策略:填充中位数;若该列原始值为整数类型,填充值自动取整。
- 连字符规范化必须在数值转换和日期解析之前执行。
- 日期标准化自动识别 Unix 时间戳(10位秒/13位毫秒),按 UTC 转日期。
- 日期防篡改校验:解析结果与原始字符串的年/月/日组件对比,不一致则置为缺失。
- 数值归一化会改变原始数据值,输出为新文件,原文件不受影响。
微信扫一扫