数据清洗实战:处理缺失值、重复值、异常值(3σ原则)
数据清洗,说白了就是给原始数据「洗澡」。我从仿真软件导出的数据,十次有八次都不干净——不是缺胳膊少腿,就是冒出几个离谱的数值。你想想看,拿这样的数据去和MATLAB联调,结果能靠谱吗?
我个人习惯,拿到数据第一件事不是急着画图,而是先做清洗。今天咱们就聊聊三种最常见的「脏数据」:缺失值、重复值、异常值。我会结合3σ原则,把实战中的坑一个个给你指出来。
一、缺失值处理:别让「空」毁了你的曲线
仿真数据里出现缺失值,原因很多。比如采样点丢失、文件传输中断、或者某些工况下传感器没响应。我在项目中遇到过最夸张的一次,一个2000行的数据集,缺失值占了15%。
处理缺失值,我一般分三步走:
- 先定位——用MATLAB的
ismissing()或Python的isnull()快速找出空值位置 - 再判断——看缺失比例,低于5%可以插值,超过20%就得考虑删除了
- 最后处理——根据数据特性选方法
常用的处理方法,我整理了一张表:
| 方法 | 适用场景 | MATLAB实现 | Python实现 |
|---|---|---|---|
| 删除缺失行 | 缺失比例低(<5%) | rmmissing(data) |
df.dropna() |
| 均值/中位数填充 | 数据波动小,缺失随机 | fillmissing(data,'constant',mean) |
df.fillna(df.mean()) |
| 线性插值 | 时序数据,变化平滑 | fillmissing(data,'linear') |
df.interpolate() |
| 前向/后向填充 | 传感器漂移或阶跃信号 | fillmissing(data,'previous') |
df.ffill() / df.bfill() |
二、重复值处理:别让「复制粘贴」骗了你
重复值在仿真数据里其实挺常见的。比如你跑了一个参数扫描,结果某个工况重复跑了两次,或者数据拼接时出了bug。我记得有一次做电机效率MAP图,就是因为没去重,画出来的等高线图全是乱的。
判断重复值,不能只看整行是否一样。我一般分两种情况:
- 完全重复——所有列都一样,直接删掉保留一条就行
- 部分重复——关键字段相同但其他字段不同,需要进一步分析
代码实现很简单:
% MATLAB:检测并删除完全重复行
[~, uniqueIdx] = unique(data, 'rows', 'stable');
data_clean = data(uniqueIdx, :);
% Python:检测并删除完全重复行
df_clean = df.drop_duplicates(keep='first')
三、异常值处理:3σ原则实战
异常值,就是那些「看着就不对」的数据点。比如你测一个温度信号,正常范围是20-80℃,结果突然蹦出一个-999或者5000。这种数据不处理,后面的分析全得崩。
处理异常值,我最常用的方法就是3σ原则。说白了,就是假设数据服从正态分布,那么99.7%的数据会落在均值±3倍标准差范围内。超出这个范围的,就认为是异常值。
具体步骤是这样的:
- 计算数据的均值μ和标准差σ
- 设定上下限:下限 = μ - 3σ,上限 = μ + 3σ
- 标记所有超出范围的数据点
- 根据业务逻辑决定是删除还是修正
来看一段完整的MATLAB代码:
% 3σ原则检测异常值
data = your_data; % 你的仿真数据
mu = mean(data, 'omitnan');
sigma = std(data, 'omitnan');
lower_bound = mu - 3 * sigma;
upper_bound = mu + 3 * sigma;
% 标记异常值
outliers = (data < lower_bound) | (data > upper_bound);
% 处理方式1:删除
data_clean = data(~outliers);
% 处理方式2:替换为边界值(我常用这个)
data_clipped = data;
data_clipped(data < lower_bound) = lower_bound;
data_clipped(data > upper_bound) = upper_bound;
Python版本也很直观:
import numpy as np
data = your_data # 你的仿真数据
mu = np.nanmean(data)
sigma = np.nanstd(data)
lower = mu - 3 * sigma
upper = mu + 3 * sigma
# 标记异常值
outliers = (data < lower) | (data > upper)
# 处理方式:替换为NaN,后续再插值
data_clean = np.where(outliers, np.nan, data)
四、知识体系总览
下面这张图,是我自己总结的数据清洗流程。每次做仿真数据处理,我都会按这个思路走一遍:
五、实战避坑指南
做了这么多年数据处理,我踩过的坑不少。挑几个典型的说说:
- 别在原始文件上直接改——我习惯先备份,或者用副本操作。万一改错了,还能找回原始数据。
- 3σ原则要配合可视化——光看数字容易误判。画个箱线图或直方图,异常值一目了然。
- 处理顺序很重要——我一般先处理缺失值,再去重,最后处理异常值。顺序乱了,结果可能也跟着乱。
- 记录每一步操作——写个简单的处理日志,方便后续复盘。这个习惯帮我省了不少回头查问题的时间。
嗯,数据清洗这块儿,今天就聊到这儿。记住一句话:干净的数据,是后续所有分析工作的基石。别嫌麻烦,这一步做扎实了,后面的MATLAB联调才能顺风顺水。