你拿到一份原始数据,字段乱、有空值、同一个人出现三遍、日期格式还不统一——这时候该从哪下手?这篇把数据清洗的主要内容拆成几条线,给一套能照着走的排查顺序,顺带说清每步做到什么程度算够,什么情况下可以跳过。
拿到一份原始数据,字段乱、有空值、同一个人出现三遍、日期格式还不统一,这时候最容易犯的错是一上来就打开脚本逐条改。更稳的做法是先划清范围:哪些活算清洗,哪些其实属于转换或特征工程,混在一起做,后面出了问题连回滚都困难。
这篇把数据清洗的主要内容拆成几条线,给一套能照着走的排查顺序,顺带说清每步做到什么程度算够、什么情况下可以跳过。如果你在做数据工程或数据接入,可以把它当成一份动手前的对照清单。涉及工具选择与接口成本的部分,到站内工具目录与价格追踪页核对当时的数字,别拍脑袋。
先划边界:清洗到底在洗什么
清洗大体落在四类活上:结构对齐、内容修正、去重合并、一致性统一。结构对齐管字段名、数据类型、字符编码是否对得上;内容修正管错值、越界值、格式错乱;去重合并处理完全重复行和同一实体的多条记录;一致性统一则管单位、统计口径和时间基准。这四类之外的动作,多半属于转换或特征工程。
- 结构对齐
- 字段、类型、编码统一到可拼接的状态
- 内容修正
- 修掉明确错误的值,而不是把数据改得更顺眼
- 去重合并
- 先定主键规则,再决定是删是并
- 一致性统一
- 口径、单位、时间基准对齐后才允许合并
动手前先问一句:这份数据下游是给报表看,还是喂给模型。给报表用,重点是把口径讲清楚、异常可解释;喂模型用,则要保留分布特征,过度清洗反而会抹掉信号。只做一次性分析的场景下,全量精修往往是浪费,最低限度可用就够了。
缺失值、重复值与异常值怎么处理
缺失值不要急着填,先分类。随机缺失和系统性缺失含义完全不同:某个来源整段数据都没有,这属于采集环节出问题,应该回头查上游,而不是在下游补一个统计值把窟窿盖上。分类之后再决定处理方式。
| 情况 | 常见处理 | 要留的痕迹 |
|---|---|---|
| 少量随机缺失 | 删行或填统计值 | 记录删除条数 |
| 系统性缺失 | 先追采集环节 | 标注来源与时间范围 |
| 关键字段缺失 | 留空加标记列 | 标记列随数据一起交付 |
| 疑似默认值填充 | 按缺失处理 | 在文档里写明判据 |
重复要分两层查。整行完全重复,通常直接去掉;实体重复则复杂得多,同一个人在多条记录里出现,字段值还可能互相冲突,这时得先定主键规则——用哪种标识、冲突时以哪条为准,再决定是合并字段还是保留最新一条。默认按时间去重是常见的坑,因为最新不等于最准。
- 先用主键候选字段统计唯一率,唯一率明显偏低说明存在实体重复
- 整行重复直接删,但要把删除前后的行数记进日志
- 实体重复先定规则:以哪个来源为准、冲突字段怎么取值
- 合并后保留一个来源标记,方便日后回溯这条记录怎么来的
- 异常值先用分位数或分组箱线图定位,再判断是错误还是真实长尾
- 落在业务不可能区间的值按错误处理,边界内的极值优先保留并标注
异常值的处理原则是:只有明确不可能的值才改。负数年龄、超出合理范围的日期,这些是错误;而边界内的极值,比如某天订单量突然翻倍,很可能是真实事件,直接删掉等于抹掉事实。拿不准时,保留原值加一列异常标记,比悄悄改掉更安全。
格式、编码与口径的一致性
格式不统一是最琐碎但最容易埋雷的一环。日期有几种写法、金额有几种币种、手机号带不带分隔符、枚举值大小写混用,这些在单表里看不出问题,一旦两表关联就全是空结果。做法是维护一张对照表,把每个字段的目标格式写死,然后按表逐项对齐。
- 建立格式对照表列出每个字段的目标类型与写法;验证方式是对清洗后的数据做类型检查,确认没有字符串混进数值列。
- 统一文本字段去首尾空白、统一全半角、统一枚举大小写;验证方式是统计枚举值种类数,确认没有同义异写。
- 对齐口径把各来源的关键指标定义写进文档,定义不一致就分列保留;验证方式是抽两条记录手工比对两种口径下的结果。
- 处理编码问题乱码、繁简混用先修源头,别在结果上批量替换;验证方式是对替换过的字段做抽样回读,确认没有连带改坏正确内容。
口径一致性最容易被跳过。两个来源都叫「活跃用户」,一个按登录算,一个按有业务动作算,直接合起来汇总就是错的。处理方式是先各自记录定义,定义对不上就分列保留,在文档里注明差异,而不是硬拼成一个字段。
怎么验收:跑一遍可复现的检查清单
清洗做完不算完,得能证明它做对了,而且下次能重跑。把每一步写成脚本或规则集,保留原始数据副本,任何时候都能对比清洗前后的差异。临时手工改的字段,往往就是后面查不出问题的根源。
- 主键唯一率:应该接近全唯一,残留重复要有解释
- 关键字段非空率:和预期对比,不能凭感觉说够了
- 枚举白名单命中率:落在允许集合内的比例
- 日期区间合理性:是否落在业务可解释的范围内
- 抽样回读:随机抽几十条对照原始记录,重点看被改过的字段
- 变更日志量级:删除和修正的条数突然变大,说明上游出了问题
# 思路示意:清洗前后各跑一遍同样的校验,把结果落盘对比
# 1. 主键唯一率 2. 关键字段非空率 3. 枚举白名单命中率
# 4. 日期范围检查 5. 变更条数统计
# 校验脚本与清洗脚本分开维护,方便定位是哪一步引入的差异被删除或修正的记录要落到一张日志表里,写明原值、新值、原因。日志不只是为了追责,它还是个预警器:某天删除量突然翻几倍,通常说明上游某个接口改了行为,这时候该去排查源头,而不是继续按老规则跑下去。
什么情况下不用做到这么细
不是所有场景都值得全量精修。探索性分析阶段,先做最低限度清洗,看清楚数据长什么样、要用的字段有哪些,再回头精修也不迟;一上来就写几百行规则,很可能等你看清需求后一大半都用不上。
- 探索阶段:只处理明显错误和结构问题,先看数据再决定精修范围
- 日志埋点类数据:重点是把解析失败的行隔离出来,不是逐条修补
- 涉及个人信息的字段:先确认脱敏与留存规则,宁可不处理也不要违规
- 上游能改就别在下游补:源头能修格式,长期看比维护清洗规则划算
- 一次性的临时分析:够用即可,别把可复现性要求套到所有场景
另外要接受一个现实:清洗规则会越堆越多,维护成本随时间上涨。判断标准很简单——如果某个字段的清洗逻辑已经复杂到需要单独写文档解释,那就该考虑推动源头改造,或者干脆在数据契约里把它约定清楚,而不是一直往下游加补丁。
下一步如果你想把这套排查顺序套到实际的接口与工具上,站内的工具目录和价格追踪页有各家的能力对比与当时的数字,先对着看再决定用哪套链路,比直接开写脚本省事。→常见问题
数据清洗和 ETL 是什么关系?
ETL 里的 T(转换)包含清洗,但清洗不只发生在转换阶段——抽取时要处理编码,加载前要校验约束。可以理解为清洗是一组贯穿流程的动作,而不是某一步。小项目里你完全可以把清洗脚本单独放着,跑完再入库,不必强求套 ETL 框架。
清洗要花多久?怎么判断可以停了?
没有固定时长,判断标准是「下游用起来不再因为数据问题返工」。实操上先定几个验收指标(主键唯一率、关键字段非空率、枚举白名单命中率),达标就停。如果清洗耗时已经超过下游用途本身的价值,说明该缩范围或直接换数据源。
清洗会不会把有用信息洗掉?
会,这其实是常见风险。删除行、填默认值、统一枚举都可能抹掉真实差异。降低风险的办法是保留原始副本、把每次修改记录到日志表、对极值优先标注而不是直接改。凡是不可逆的操作,都先跑一遍差异对比再决定。