一、大数据时代的数据清洗痛点
每天产生的数据量像洪水一样涌来,但真正能用的却不多。就像淘金一样,得先把沙子筛掉才能找到金子。数据清洗就是这个筛沙子的过程,但现实中很多团队都在这件事上栽跟头。
最常见的问题就是默认值处理不当。比如用户年龄填0、收入填-1、地址写"测试",这些数据要是直接喂给算法,结果肯定惨不忍睹。去年我们团队就遇到过,一个推荐系统把测试账号当成了真实用户,结果给所有人推荐情趣用品,差点闹出大笑话。
二、数据清洗的四大拦路虎
1. 缺失值处理
数据库里经常能看到NULL值,但NULL和NULL还不一样。有的是用户真没填,有的是系统出bug漏掉了,还有的是ETL过程丢的。比如下面这个用户表:
-- MySQL示例:包含多种缺失情况的用户表
CREATE TABLE users (
id INT PRIMARY KEY,
name VARCHAR(50) NOT NULL, -- 必填字段
age INT, -- 可选的用户年龄
income DECIMAL(10,2), -- 可能为NULL的收入
last_login DATETIME -- 未登录用户为NULL
);
-- 典型问题数据示例
INSERT INTO users VALUES
(1, '张三', 25, 5000.00, '2023-01-15'),
(2, '李四', NULL, NULL, NULL), -- 新注册未完善资料
(3, '测试用户', 0, -1, '2023-02-01'); -- 测试数据污染
2. 异常值检测
有些数据看起来像模像样,实则暗藏杀机。比如:
- 年龄200岁
- 身高3米
- 订单金额9999999元
# Python+Pandas异常值检测示例
import pandas as pd
def detect_outliers(df):
# 定义合理范围
rules = {
'age': (0, 120),
'height': (0.5, 2.5), # 单位:米
'order_amount': (0, 100000) # 假设正常订单不超过10万
}
outliers = pd.DataFrame()
for col, (min_val, max_val) in rules.items():
if col in df.columns:
condition = (df[col] < min_val) | (df[col] > max_val)
outliers = pd.concat([outliers, df[condition]])
return outliers.drop_duplicates()
# 测试数据
data = {'age': [25, 200, 35], 'height': [1.75, 2.8, 1.65], 'order_amount': [100, 9999999, 50]}
df = pd.DataFrame(data)
print(detect_outliers(df))
3. 格式混乱
同一个手机号可能有"13800138000"、"138-0013-8000"、"138 0013 8000"三种写法。日期格式更是重灾区,有"2023/01/01"、"01-01-2023"、"January 1, 2023"等各种变体。
4. 数据重复
同样的订单在系统里存了5次,或者用户注册了3个账号但用的是同一个手机号。去重听着简单,实际操作起来要考虑很多业务规则。
三、数据清洗的十八般武艺
1. 缺失值处理三板斧
- 直接删除:简单粗暴,适合缺失比例小的数据
-- MySQL删除缺失示例
DELETE FROM users WHERE age IS NULL AND income IS NULL;
- 默认值填充:业务逻辑决定默认值
# Pandas填充示例
df['age'].fillna(30, inplace=True) # 用平均年龄填充
df['income'].fillna(method='ffill', inplace=True) # 前向填充
- 预测填充:用机器学习预测缺失值
from sklearn.ensemble import RandomForestRegressor
def predict_missing(df, target_col):
# 分割有值和缺失的数据
known = df[df[target_col].notnull()]
unknown = df[df[target_col].isnull()]
# 准备特征和标签
X = known.drop(target_col, axis=1)
y = known[target_col]
# 训练模型
model = RandomForestRegressor()
model.fit(X, y)
# 预测缺失值
predicted = model.predict(unknown.drop(target_col, axis=1))
df.loc[df[target_col].isnull(), target_col] = predicted
return df
2. 异常值处理技巧
- 分位数法:把超过99%分位数的数据视为异常
# 分位数检测示例
Q1 = df['order_amount'].quantile(0.25)
Q3 = df['order_amount'].quantile(0.75)
IQR = Q3 - Q1
upper_bound = Q3 + 1.5 * IQR
lower_bound = Q1 - 1.5 * IQR
- 业务规则法:根据业务常识设定阈值
-- SQL业务规则示例
SELECT * FROM orders
WHERE amount > 100000 -- 单笔订单超过10万视为异常
OR create_time < '2020-01-01'; -- 三年前的订单可能有问题
3. 格式标准化套路
- 正则表达式大法:统一电话号码格式
import re
def standardize_phone(phone):
# 移除非数字字符
cleaned = re.sub(r'[^\d]', '', str(phone))
# 验证长度并格式化
if len(cleaned) == 11:
return f"{cleaned[:3]}-{cleaned[3:7]}-{cleaned[7:]}"
return None
print(standardize_phone("138-0013-8000")) # 输出: 138-0013-8000
print(standardize_phone("138 0013 8000")) # 输出: 138-0013-8000
- 日期解析库:处理各种日期格式
from dateutil import parser
def parse_date(date_str):
try:
return parser.parse(date_str).strftime('%Y-%m-%d')
except:
return None
print(parse_date("January 1, 2023")) # 输出: 2023-01-01
print(parse_date("01/01/23")) # 输出: 2023-01-01
四、实战中的避坑指南
1. 不要过度清洗
某电商公司曾把"收货地址是南极洲"的订单全删了,后来发现那是个科研机构的采购需求,错失了百万订单。清洗规则要保留一定的灵活性。
2. 记录清洗过程
建议创建清洗日志表:
-- MySQL清洗日志表示例
CREATE TABLE data_cleaning_log (
id INT AUTO_INCREMENT PRIMARY KEY,
table_name VARCHAR(50) NOT NULL,
column_name VARCHAR(50) NOT NULL,
operation VARCHAR(20) NOT NULL, -- 如'delete','fill','modify'
original_value TEXT,
new_value TEXT,
reason VARCHAR(255),
process_time DATETIME DEFAULT CURRENT_TIMESTAMP
);
3. 分批处理大数据
用Python处理1TB数据?内存会炸的!建议:
# 分块处理大文件示例
chunk_size = 100000 # 每次处理10万行
for chunk in pd.read_csv('huge_file.csv', chunksize=chunk_size):
process_chunk(chunk) # 自定义处理函数
chunk.to_csv('cleaned_data.csv', mode='a', header=False)
4. 测试清洗效果
清洗前后要对比统计特征:
# 数据分布对比示例
original_stats = df.describe()
cleaned_stats = cleaned_df.describe()
pd.concat([original_stats, cleaned_stats],
axis=1,
keys=['Original', 'Cleaned'])
五、数据清洗的未来趋势
现在越来越多的团队开始用AI辅助数据清洗。比如:
- 用NLP技术解析非结构化数据
- 用GAN生成合理的数据填充缺失值
- 用图神经网络检测复杂关系中的异常
不过这些高级方法都需要大量训练数据,中小公司可能更适合传统的规则引擎+机器学习组合方案。
六、总结与建议
数据清洗就像做菜前的备料,直接决定最终菜品质量。根据我们的经验,给出三点建议:
- 建立数据质量监控:设置数据质量KPI,比如缺失率<5%、异常值<1%
- 开发可复用的清洗工具:把常用清洗逻辑封装成函数或SQL脚本
- 业务人员参与规则制定:避免技术人员闭门造车导致误伤有效数据
记住,没有完美的清洗方案,只有最适合业务场景的方案。有时候保留一些"脏数据"反而能发现业务问题,关键是要建立数据治理的全流程意识。
评论