数据清洗实战:处理缺失值、重复值、异常值(3σ原则)

数据清洗,说白了就是给原始数据「洗澡」。我从仿真软件导出的数据,十次有八次都不干净——不是缺胳膊少腿,就是冒出几个离谱的数值。你想想看,拿这样的数据去和MATLAB联调,结果能靠谱吗?

我个人习惯,拿到数据第一件事不是急着画图,而是先做清洗。今天咱们就聊聊三种最常见的「脏数据」:缺失值、重复值、异常值。我会结合3σ原则,把实战中的坑一个个给你指出来。

核心观点:数据清洗不是可选项,而是仿真数据处理的「入场券」。跳过这一步,后面的分析全是白费功夫。

一、缺失值处理:别让「空」毁了你的曲线

仿真数据里出现缺失值,原因很多。比如采样点丢失、文件传输中断、或者某些工况下传感器没响应。我在项目中遇到过最夸张的一次,一个2000行的数据集,缺失值占了15%。

处理缺失值,我一般分三步走:

  1. 先定位——用MATLAB的ismissing()或Python的isnull()快速找出空值位置
  2. 再判断——看缺失比例,低于5%可以插值,超过20%就得考虑删除了
  3. 最后处理——根据数据特性选方法

常用的处理方法,我整理了一张表:

方法 适用场景 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()
我的小技巧:处理时序仿真数据时,我优先用线性插值。因为它能保持数据的连续性,不会像均值填充那样引入「台阶」。但要注意——如果缺失值连续超过3个,插值结果可能失真,这时候我会考虑分段处理。

二、重复值处理:别让「复制粘贴」骗了你

重复值在仿真数据里其实挺常见的。比如你跑了一个参数扫描,结果某个工况重复跑了两次,或者数据拼接时出了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倍标准差范围内。超出这个范围的,就认为是异常值。

具体步骤是这样的:

  1. 计算数据的均值μ和标准差σ
  2. 设定上下限:下限 = μ - 3σ,上限 = μ + 3σ
  3. 标记所有超出范围的数据点
  4. 根据业务逻辑决定是删除还是修正

来看一段完整的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σ原则不是万能的。如果数据本身就不服从正态分布(比如有多个峰值),或者样本量太小(<30个点),3σ原则会误判很多正常数据。这时候我建议改用IQR(四分位距)法,或者结合业务知识手动设定阈值。

四、知识体系总览

下面这张图,是我自己总结的数据清洗流程。每次做仿真数据处理,我都会按这个思路走一遍:

数据清洗知识体系总览 原始仿真数据 缺失值处理 重复值处理 异常值处理 缺失值处理方法 • 删除缺失行 • 均值/中位数填充 • 线性插值 / 前向后向填充 重复值处理方法 • 完全重复 → 直接删除 • 部分重复 → 分析后处理 • 保留第一条或最后一条 异常值处理方法 • 3σ原则(正态分布) • IQR四分位距法 • 业务阈值手动设定 清洗结果验证 干净数据 → 联调分析 💡 验证方法: 统计量对比 + 可视化检查

五、实战避坑指南

做了这么多年数据处理,我踩过的坑不少。挑几个典型的说说:

  • 别在原始文件上直接改——我习惯先备份,或者用副本操作。万一改错了,还能找回原始数据。
  • 3σ原则要配合可视化——光看数字容易误判。画个箱线图或直方图,异常值一目了然。
  • 处理顺序很重要——我一般先处理缺失值,再去重,最后处理异常值。顺序乱了,结果可能也跟着乱。
  • 记录每一步操作——写个简单的处理日志,方便后续复盘。这个习惯帮我省了不少回头查问题的时间。
一个小建议:刚开始做数据清洗时,别追求一步到位。先跑一遍基础清洗,看看数据长什么样,再决定要不要用更复杂的方法。有时候,简单的删除+插值组合,效果反而比花里胡哨的算法好。

嗯,数据清洗这块儿,今天就聊到这儿。记住一句话:干净的数据,是后续所有分析工作的基石。别嫌麻烦,这一步做扎实了,后面的MATLAB联调才能顺风顺水。