3、数据清洗基础:缺失值处理、重复数据去重、数据类型转换、异常值过滤

说实话,很多做OA报表的人,拿到数据就直接开干。画图表、做透视、搞联动,忙得不亦乐乎。结果呢?报表一出来,领导一看:「这数据不对吧?」—— 嗯,我当年就踩过这个坑。

数据清洗,说白了就是给你的数据「洗个澡」。脏数据不处理,后面所有分析都是白搭。今天咱们就把这四块硬骨头啃下来。

3.1 缺失值处理:别让空值毁了你的报表

我在项目中遇到过最典型的情况:考勤报表里,某员工的打卡记录全是空的。你以为是旷工?其实人家那天出差,系统没录入。这就是缺失值带来的误导。

缺失值处理,一般有三种思路:

  • 直接删除:如果缺失比例很小(比如不到5%),直接删掉整行。简单粗暴,但有效。
  • 填充默认值:比如数值型字段填0,文本型字段填「未知」。适合业务上允许「占位」的场景。
  • 用统计值填充:用均值、中位数、众数去填。我个人习惯用中位数,因为它不受极端值影响。

核心原则:缺失值处理没有银弹。你得先搞清楚「为什么缺失」,再决定怎么处理。

举个例子,OA系统里的审批流程数据:

# 伪代码示例
# 1. 检查缺失比例
missing_rate = df['审批时长'].isnull().sum() / len(df)

# 2. 如果小于5%,直接删除
if missing_rate < 0.05:
    df.dropna(subset=['审批时长'], inplace=True)

# 3. 否则用中位数填充
else:
    median_val = df['审批时长'].median()
    df['审批时长'].fillna(median_val, inplace=True)

小技巧:我曾经处理过一份合同数据,金额字段缺失严重。后来发现,缺失的合同都是「框架协议」,金额为0是合理的。所以,我直接填了0,而不是用均值。你看,业务理解比技术更重要。

3.2 重复数据去重:别让一条数据算两遍

重复数据在OA系统里太常见了。比如员工提交报销单,网络卡顿,点了两次提交。结果数据库里就多了两条一模一样的记录。你想想看,汇总报销金额时,这笔钱就被算了两次。

去重,我一般分两步走:

  1. 完全重复:所有字段都一样。直接用 drop_duplicates() 干掉。
  2. 部分重复:只有关键字段重复。比如「工号+日期」重复,但备注不同。这时候得按业务规则保留一条。
# 完全去重
df.drop_duplicates(inplace=True)

# 按关键字段去重,保留第一条
df.drop_duplicates(subset=['工号', '日期'], keep='first', inplace=True)

注意:去重前一定要备份原始数据。我见过有人直接覆盖了原始表,结果发现「重复」其实是业务允许的。嗯,那场面,相当尴尬。

3.3 数据类型转换:别让数字变成文本

这个问题,做报表的人几乎天天遇到。从OA系统导出的数据,经常是「看起来是数字,实际上是文本」。你求和、求平均,结果全是0或者报错。

为什么会这样?因为系统导出时,某些字段带了不可见字符,或者数字里混了逗号、百分号。

我个人的习惯是,拿到数据先检查类型:

# 查看每列的数据类型
print(df.dtypes)

# 强制转换
df['金额'] = pd.to_numeric(df['金额'], errors='coerce')
df['日期'] = pd.to_datetime(df['日期'], errors='coerce')

这里有个坑:errors='coerce' 会把无法转换的值变成 NaN。所以转换后,记得再处理一遍缺失值。

避坑指南:我曾经处理过一份考勤数据,「工作时长」字段里混了「8h」「7.5h」这样的文本。直接转换肯定报错。我的做法是:先替换掉「h」,再转成数值。说白了,就是先清洗,再转换。

3.4 异常值过滤:别让极端值带偏了分析

异常值,就是那些「明显不合理」的数据。比如员工年龄200岁,月薪100万,出差天数365天。这些数据如果不处理,你的平均值、标准差全都会被带偏。

判断异常值,我常用两种方法:

  • 业务规则法:比如年龄在18-65岁之间,超出就是异常。简单直接,适合有明确业务边界的场景。
  • 统计方法(3σ原则):超出均值±3倍标准差的值,视为异常。适合没有明确业务边界的数值型数据。
# 业务规则法
df = df[(df['年龄'] >= 18) & (df['年龄'] <= 65)]

# 3σ原则
mean = df['报销金额'].mean()
std = df['报销金额'].std()
df = df[(df['报销金额'] >= mean - 3*std) & (df['报销金额'] <= mean + 3*std)]

记住:异常值不一定是错误值。比如CEO的报销金额特别高,可能只是因为他出差多。所以,过滤前先确认:这个值是真的异常,还是业务上的特殊情况?

嗯,数据清洗这块,说难不难,说简单也不简单。核心就一句话:你对业务理解有多深,你的数据就有多干净。下一章咱们聊聊「数据聚合与分组统计」,到时候你会更深刻地体会到:清洗这一步,省不了。