数据清洗基础:缺失值处理与异常值检测
数据清洗这件事,说白了就是给数据「洗澡」。我在智慧农业项目里接手过不少传感器数据,那叫一个脏——缺胳膊少腿的、数值离谱的、重复记录的,什么都有。今天咱们就聊聊最基础的三个活儿:缺失值怎么处理、异常值怎么揪出来、重复数据怎么去重。
你想想看,传感器在田里风吹日晒,信号断一下、电池掉个电,数据就缺了一块。这很正常。关键是你得知道怎么补,或者干脆扔掉。
缺失值处理策略
缺失值,就是数据表里那些空着的格子。我习惯先问三个问题:缺了多少?为什么缺?缺的值重要吗?
1. 直接删除
最简单粗暴的方法。但别乱删,得看情况。
- 行删除:某条记录缺了关键字段,直接删掉整行。比如土壤pH值缺失,这条数据基本废了。
- 列删除:某个字段超过70%都是空的,那这个字段留着也没意义。我在处理某大棚温度数据时,有个「地下50cm温度」字段,90%都是空值,直接砍掉。
2. 填充法
不删,那就填。填什么?得有点依据。
| 填充方式 | 适用场景 | 我踩过的坑 |
|---|---|---|
| 均值/中位数填充 | 数值型数据,分布较对称 | 某次用均值填充土壤湿度,结果把干旱期的数据全拉高了,模型误判 |
| 众数填充 | 分类数据,比如天气类型 | 还行,但注意类别要均衡 |
| 前向/后向填充 | 时间序列数据,比如每5分钟的温度 | 传感器断连时,用前一条数据填充,比瞎猜靠谱 |
| 固定值填充 | 你知道缺失值代表什么含义 | 比如「未检测到」填0,但得确认0不是有效值 |
3. 插值法
插值比填充更「聪明」一点。它不是简单填个平均值,而是根据前后数据的变化趋势来推算。
常用的有线性插值和样条插值。我举个线性插值的例子:
# 假设时间点1温度20度,时间点3温度26度
# 时间点2缺失,用线性插值:
# (20 + 26) / 2 = 23度
# 用pandas实现
import pandas as pd
df['temperature'].interpolate(method='linear', inplace=True)
嗯,这里要注意:插值只适合数据变化比较平滑的情况。如果数据忽高忽低,插值反而会引入误差。我在处理风速数据时就吃过这个亏——风速变化太随机,插出来的值完全不对。
异常值检测方法
异常值,就是那些「离谱」的数据。比如土壤温度突然蹦到80度,那肯定是传感器抽风了。怎么揪出来?我常用两种方法。
1. 3σ 法则
这个法子基于正态分布。简单说:数据落在均值±3个标准差之外的概率只有0.3%,那这些点就可能是异常。
import numpy as np
def detect_outliers_3sigma(data):
mean = np.mean(data)
std = np.std(data)
lower = mean - 3 * std
upper = mean + 3 * std
outliers = data[(data < lower) | (data > upper)]
return outliers
但有个前提:数据得大致符合正态分布。我在处理大棚二氧化碳浓度数据时,发现它偏态严重,3σ 法则直接误判了20%的正常数据。所以,用之前先看看数据分布。
2. IQR 方法
IQR 是四分位距,不依赖正态分布,更鲁棒。它的逻辑是:
- 计算 Q1(25%分位数)和 Q3(75%分位数)
- IQR = Q3 - Q1
- 正常范围:Q1 - 1.5×IQR 到 Q3 + 1.5×IQR
- 超出这个范围的就是异常
def detect_outliers_iqr(data):
Q1 = data.quantile(0.25)
Q3 = data.quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
outliers = data[(data < lower) | (data > upper)]
return outliers
重复数据去重
重复数据,就是一模一样的记录出现了多次。原因很多:传感器重复上报、数据采集程序bug、人工录入手抖等等。
去重其实不复杂,但有个坑:你得先定义什么叫「重复」。
- 完全重复:所有字段都一样。直接删掉多余的。
- 部分重复:关键字段一样,但其他字段不同。比如同一时间点的温度记录了两条,数值略有差异。这时候得看业务逻辑——取平均值?取最新?还是取置信度高的?
# 完全去重
df.drop_duplicates(inplace=True)
# 按指定列去重,保留第一条
df.drop_duplicates(subset=['timestamp', 'sensor_id'], keep='first', inplace=True)
我曾经遇到过一个案例:某大棚的湿度数据,同一个时间点出现了3条记录,数值都不同。后来发现是传感器和网关之间的通信协议有bug,导致数据重复上报。最后我们按时间戳去重,取中位数作为最终值。
知识体系总览
下面这张图,把咱们今天讲的内容串起来了。你可以把它当成一个决策流程:拿到脏数据,先看缺不缺,再看有没有异常,最后查重。
这张图里,我特意把顺序标出来了。为什么先处理缺失值?因为缺失值会影响后续的异常值检测——比如你用3σ法则时,缺失值太多会把均值和标准差带偏。去重放最后,是因为填充或插值后,可能会产生新的重复记录,一次性处理更干净。
好了,数据清洗的基础就这些。说白了就是三板斧:缺了就补、离谱就揪、重复就删。但每一板斧都有讲究,用对了事半功倍,用错了数据越洗越脏。下次你拿到传感器数据,不妨先按这个流程走一遍,心里就有底了。