缺失值的处理
由于各种原因,我们使用的数据集或多或少地存在着缺失值。如果直接删除缺失值,会丢失其他有价值的数据,以下是处理缺失值的几种方法。
1. 直接删除
当缺失值的个数只占整体很小一部分的时候,可直接删除缺失值。但是如果缺失值占比上升,这种缺失值处理方法误差就很大了。
在采用删除法处理缺失值时,需要首先检测样本总体中缺失值的个数。python中统计缺失值的方法如下:
import numpy as np
import pandas as pd
data = pd.read_csv('data.csv',encoding='GBK')
# 将空值形式的缺失值转换成可识别的类型
data = data.replace(' ', np.NaN)
print(data.columns)#['id', 'label', 'a', 'b', 'c', 'd']
#将每列中缺失值的个数统计出来
null_all = data.isnull().sum()
#id 0
#label 0
#a 7
#b 3
#c 3
#d 8
#查看a列有缺失值的数据
a_null = data[pd.isnull(data['a'])]
#a列缺失占比
a_ratio = len(data[pd.isnull(data['a'])])/len(data) #0.0007
#丢弃缺失值,将存在缺失值的行丢失
new_drop = data.dropna(axis=0)
print(new_drop.shape)#(9981,6)
#丢弃某几列有缺失值的行
new_drop2 = data.dropna(axis=0, subset=['a','b'])
print(new_drop2.shape)#(9990,6)
上述数据缺失值较少,可直接删除。注意,在计算缺失值时,对于缺失值不是NaN的要用replace()函数替换成NaN格式,否则pd.isnull()检测不出来。
2.使用一个全局常量填充缺失值
可以用一个常数('Unknow’或者负无限大)来填充缺失值。但是如果缺失值较多,都用’Unknow’来填充的话,数据挖掘程序会觉得’Unknow’是一有趣的概念。该方法很简单,但十分不可靠。python实现如下:
#用0填充缺失值
fill_data = data.fillna('Unknow')
print(fill_data.isnull().sum())
#out
id 0
label 0
a 0
b 0
c 0
d 0
3.均值、众数、中位数填充
根据样本之间的相似性填补缺失值是指用这些缺失值最可能的值来填补它们,通常使用能代表变量中心趋势的值进行填补,代表变量中心趋势的指标包括平均值、中位数、众数等,那么我们采用哪些指标来填补缺失值呢?
分布类型 | 填充值 | 原因 |
近正态分布 | 平均值 | 所有观测值都较好地聚集在平均值周围 |
偏态分布 | 中位数 | 偏态分布的大部分值都聚集在变量分布的一侧,中位数是更好地代表数据中心趋势的指标 |
有离群点的分布 | 中位数 | 中位数是更好地代表数据中心趋势的指标 |
名义变量 | 众数 | 名义变量无大小、顺序之分,不能加减乘除。如性别 |
python实现如下:
#均值填充
data['a'] = data['a'].fillna(data['a'].mean())
#中位数填充
data['a'] = data['a'].fillna(data['a'].median())
#众数填充
data['a'] = data['a'].fillna(stats.mode(data['a'])[0][0])
#用前一个数据进行填充
data['a'] = data['a'].fillna(method='pad')
#用后一个数据进行填充
data['a'] = data['a'].fillna(method='bfill')
Imputer提供了缺失数值处理的基本策略,比如使用缺失数值所在行或列的均值、中位数、众数来替代缺失值。
from sklearn.preprocessing import Imputer
imr = Imputer(missing_values='NaN', strategy='mean', axis=0)
imr = imr.fit(data.values)
imputed_data = pd.DataFrame(imr.transform(data.values))
print(imputed_data[0:15])
参数 | 描述 |
missing_values | int或’NaN’,默认NaN(String类型) |
strategy | mean,默认平均值填补;可选,median(中位数),most_frequent(众数) |
axis | 指定轴向。axis=0,列向(默认);axis=1,行向 |
verbose | int默认值为0 |
copy | 默认True:创建数据集的副本;False:在任何地方都可进行插值 |
4. 插值法、KNN填充
- 插值法
interpolate()插值法,计算的是缺失值前一个值和后一个值的平均数。
data['a'] = data['a'].interpolate()
- KNN填充
from fancyimpute import KNN
fill_knn = KNN(k=3).fit_transform(data)
data = pd.DataFrame(fill_knn)
print(data.head())
#out
0 1 2 3 4 5
0 111.0 0.0 2.0 360.0 4.000000 1.0
1 112.0 1.0 9.0 1080.0 3.000000 1.0
2 113.0 1.0 9.0 1080.0 2.000000 1.0
3 114.0 0.0 1.0 360.0 *3.862873 *1.0
4 115.0 0.0 1.0 270.0 5.000000 1.0
5.随机森林填充
from sklearn.ensemble import RandomForestRegressor
#提取已有的数据特征
process_df = data.ix[:, [1, 2, 3, 4, 5]]
# 分成已知该特征和未知该特征两部分
known = process_df[process_df.c.notnull()].as_matrix()
uknown = process_df[process_df.c.isnull()].as_matrix()
# X为特征属性值
X = known[:, 1:3]
# print(X[0:10])
# Y为结果标签
y = known[:, 0]
print(y)
# 训练模型
rf = RandomForestRegressor(random_state=0, n_estimators=200, max_depth=3, n_jobs=-1)
rf.fit(X, y)
# 预测缺失值
predicted = rf.predict(uknown[:, 1:3])
print(predicted)
#将预测值填补原缺失值
data.loc[(data.c.isnull()), 'c'] = predicted
print(data[0:10])