Python数据分析之缺失值处理
数据清洗主要是删除原始数据集中的无关数据、重复数据,平滑噪声数据,去除与数据挖掘主题无关的数据,处理缺失值、异常值等
类型
缺失主要为完全随机缺失,随机缺失和非随机缺失
完全随机缺失(missing completely at random, MCAR)
数据的缺失是随机的,数据的缺失不依赖于任何不完全变量或完全变量。
随机缺失(missing at random,MAR)
数据的缺失不是完全随机的,即该类数据的缺失依赖于其他完全变量。
完全非随机缺失(missing not at random,MNAR)
数据的缺失依赖于不完全变量自身
处理方式
处理方式分为3类,删除记录、数据插补和不处理
# 生成数据
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(6,4), columns=['A','B','C','D',]) # 生成数据
df.iloc[1:2, 1] = np.nan #增加缺失值
df.iloc[3,2] = np.nan
df.iloc[4,3] = np.nan
df
A | B | C | D | |
---|---|---|---|---|
0 | -1.078160 | -2.039581 | 2.353353 | 0.561535 |
1 | 0.688913 | NaN | 0.770112 | -1.633434 |
2 | 2.540337 | 1.256162 | -1.327333 | -0.023861 |
3 | 0.191514 | 0.831956 | NaN | -0.083259 |
4 | -0.845405 | -1.113420 | 0.236066 | NaN |
5 | -0.606298 | 1.322792 | -0.637305 | 0.560106 |
# 查看缺失值
nan_all = df.isnull()
nan_all
A | B | C | D | |
---|---|---|---|---|
0 | False | False | False | False |
1 | False | True | False | False |
2 | False | False | False | False |
3 | False | False | True | False |
4 | False | False | False | True |
5 | False | False | False | False |
nan_col1 = df.isnull().any() # 获得含有空值的列
nan_col1
A False
B True
C True
D True
dtype: bool
nan_col2 = df.isnull().all() # 获得全部为空值的列
nan_col2
A False
B False
C False
D False
dtype: bool
df1 = df.dropna() # 直接删除空数据
df1
A | B | C | D | |
---|---|---|---|---|
0 | -1.078160 | -2.039581 | 2.353353 | 0.561535 |
2 | 2.540337 | 1.256162 | -1.327333 | -0.023861 |
5 | -0.606298 | 1.322792 | -0.637305 | 0.560106 |
数据插值
常用插值方法:
- 均值/中位数/众数插补
于定量(定比)数据:使用平均数(mean)或中位数(median)填补,比如一个班级学生的身高特征,对于一些同学缺失的身高值就可以使用全班同学身高的平均值或中位数来填补 - 使用固定值
- 最近邻插补
- 回归方法
- 插值法
- 热卡填补
热卡填充法是在完整数据中找到一个与它最相似的对象,然后用这个相似对象的值来进行填充。通常会找到超出一个的相似对象,在所有匹配对象中没有最好的,而是从中随机的挑选一个作为填充值。 - K最近邻算法
另外一种方法就是利用无监督机器学习的聚类方法。通过K均值的聚类方法将所有样本进行聚类划分,然后再通过划分的种类的均值对各自类中的缺失值进行填补。归其本质还是通过找相似来填补缺失值 - 拟合缺失值
拟合就是利用其它变量做模型的输入进行缺失变量的预测,与我们正常建模的方法一样,只是目标变量变为了缺失值 - 最大似然估计
在缺失类型为随机缺失的条件下,假设模型对于完整的样本是正确的,那么通过观测数据的边际分布可以对未知参数进行极大似然估计(Little and Rubin)。这种方法也被称为忽略缺失值的极大似然估计,对于极大似然的参数估计实际中常采用的计算方法是期望值最大化(Expectation Maximization,EM)。该方法比删除个案和单值插补更有吸引力,它一个重要前提:适用于大样本。有效样本的数量足够以保证ML估计值是渐近无偏的并服从正态分布。但是这种方法可能会陷入局部极值,收敛速度也不是很快,并且计算很复杂,且仅限于线性模型 - 多重插补
多值插补的思想来源于贝叶斯估计,认为待插补的值是随机的,它的值来自于已观测到的值。具体实践上通常是估计出待插补的值,然后再加上不同的噪声,形成多组可选插补值。根据某种选择依据,选取最合适的插补值
- 为每个缺失值产生一套可能的插补值,这些值反映了无响应模型的不确定性
- 每个插补数据集合都用针对完整数据集的统计方法进行统计分析
- 对来自各个插补数据集的结果,根据评分函数进行选择,产生最终的插补值
# 均值/中位数/众数插补
df_mean = df.fillna(np.mean(df)) # 均值
df_mean
# df_median = df.fillna(np.median(df)) #中位数
# df_median
# df_mode = df.fillna(np.argmax(np.bincount(df))) # 众数
# df_mode
A | B | C | D | |
---|---|---|---|---|
0 | -1.078160 | -2.039581 | 2.353353 | 0.561535 |
1 | 0.688913 | 0.051582 | 0.770112 | -1.633434 |
2 | 2.540337 | 1.256162 | -1.327333 | -0.023861 |
3 | 0.191514 | 0.831956 | 0.278979 | -0.083259 |
4 | -0.845405 | -1.113420 | 0.236066 | -0.123783 |
5 | -0.606298 | 1.322792 | -0.637305 | 0.560106 |
# 拉格朗日插值
from scipy.interpolate import lagrange ## 导入拉格朗日插值函数
# s为列向量,n为被插值的位置,k为取前后的数据个数,默认5个
def ployinterp_columns(s, n, k=5):
y = s[list(range(n-k ,n)) + list(range(n+1, n+1+k))] # 取数
y = y[y.notnull()] # 剔除空值
return lagrange(y.index, list(y))(n) # 插值并返回插值结果
# 逐个元素判断是否需要插值
for i in df.columns:
for j in range(len(df)):
if (df[i].isnull())[j]: # 如果为空即插值
df[i][j] = ployinterp_columns(df[i], j)
print(df)
A B C D
0 -1.078160 -2.039581 2.353353 0.561535
1 0.688913 -0.937481 0.770112 -1.633434
2 2.540337 1.256162 -1.327333 -0.023861
3 0.191514 0.831956 -1.295290 -0.083259
4 -0.845405 -1.113420 0.236066 -1.752516
5 -0.606298 1.322792 -0.637305 0.560106