数据预处理之缺失值的处理

缺失值的类型

首先对数据的变量(特征)按照缺失和不缺失进行分类:不含有缺失值的变量称为完全变量,含有缺失值的变量称为非完全变量。

缺失值的类型分为三种:完全随机缺失,随机缺失和非随机缺失。

完全随机缺失: 缺失的变量和其余的变量没有关系。比如”家庭住址“这个信息,和”身高“等其余的变量没有关系。

随机缺失: 缺失的变量和完全变量存在一定的关系。假如“学历”中不含缺失值,“收入”和它有关,那么“收入”为随机缺失。

非随机缺失:缺失的变量和非完全变量存在一定的关系。

根据上面变量的分类,其实我们已经大致可以想出来一些处理缺失值的方法了:比如对于完全随机缺失,我们可以选择丢弃或者是依靠变量自身未缺失值的信息(均值、方差)进行补全。 而对于随机缺失,我们可以利用完全变量的信息来进行补全。

数据处理的方法

  总的来说,在处理缺失值的时候我们可以采用三种方法,第一种是不作处理,这个很简单,把缺失值放在那里就可以了。 第二种方法是进行删除操作。 第三种方法就是进行数据的补全操作。

删除操作

当某个特征上面的数据缺失太大的时候,直接将这个特征删除了。

而当特征上面的缺失值很少的时候,比如只有几个缺失值的时候,可以考虑把包含这些缺失值的元组进行删除。

补全操作

实际当中用的最多的还是补全操作,补全操作有很多种,按照参考文章一的划分有很多种,可以看原文查看具体的类型,这里我只介绍自己目前明白的几种:

1:人工填充:根据已经掌握的数据的知识进行填充,但是这个方法在数据量很大,缺失值很多的时候明显是不可以的。

2:特殊值填充:将缺失值用unknown表示,这和原来的缺失值的意思还是有一点差别的。在这里unknown可以当做一种取值的可能性。

3:平均值填充。 对于数字类型的变量,可以使用没有缺失值的一些信息进行估计,使用用平均值进行的估计称为平均值填充。对于分类变量可以使用众数来进行填充。其实也可以加上一点方差的信息来进行估计,我在后面的例子当中来说明这一点。

4:将数据映射到高维,第二个参考文章。这个方法有点暴力,使得特征的数量大大的增加,但是保留原始数据的全部信息。

5:使用其它的变量来进行预估。 这里的方法就多了,包括文章中讲的回归,期望最大化方法和C4.5方法。这里因为都没有接触过,就不写了。

下面我将用一些例子来说明如何如何处理缺失值

使用pandas来处理泰坦尼克号的数据

数据集的准备:

  我们使用kaggle 的titanic的数据来进行实验,https://www.kaggle.com/c/titanic/data 

首先导入数据集

import pandas as pd
train_df = pd.read_csv('../input/train.csv')
print(train_df.info())

看一下各个特征里面数据的缺失情况

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 891 entries, 0 to 890
Data columns (total 12 columns):
PassengerId    891 non-null int64
Survived       891 non-null int64
Pclass         891 non-null int64
Name           891 non-null object
Sex            891 non-null object
Age            714 non-null float64
SibSp          891 non-null int64
Parch          891 non-null int64
Ticket         891 non-null object
Fare           891 non-null float64
Cabin          204 non-null object
Embarked       889 non-null object
dtypes: float64(2), int64(5), object(5)
memory usage: 83.6+ KB

其中Age,Cabin,和Embarked三个数据有缺失,

 

对Cabin和Embarked进行处理

对于Cabin的数据,因为它的缺失值太多了,所以我们的做法就是直接删除掉,直接把这一个特征删除了就可以了

train_df = train_df.drop(['Cabin'], axis=1)

对于Embarked特征来说,它有两个缺失值,我们可以删除了包含有缺失值的两条记录

train_df = train_df.drop(train_df[train_df['Embarked'].isnull()].index, axis=0)

也可以用众数进行填充

embarked_mode = train_df['Embarked'].mode()[0]
train_df['Embarked'] = train_df['Embarked'].fillna(embarked_mode)

 

于Age信息的补全

最容易想到的就是用平均值来进行补充

age_mean = train_df['Age'].dropna().mean()
train_df['Age'] = train_df['Age'].fillna(age_mean)

当然也可以利用均值和方差(标准差)的信息进行一些填充

import numpy as np
age_mean = train_df['Age'].dropna().mean()
age_std = train_df['Age'].dropna().std()
age_nan_num = train_df['Age'].isnull().sum()
#在 (均值-标准差) 和 (均值+标准差) 之间产生一些均分分布的数作为填充
fill_age = np.random.randint(age_mean - age_std, age_mean + age_std , size=age_nan_num)
train_df.loc[train_df['Age'].isnull(),'Age'] = fill_age

此外,就是利用别的属性的信息进行填充,比如在泰塔尼克号数据当中,我们分析性别和登陆的港口不同,他们的年龄可能也不同,于是我们可以这样做,为每个类别的人填充不同的值。

#先将数据转换一下,好进行处理
train_df['Sex'] = train_df['Sex'].map({'male':0, 'female':1})
train_df['Embarked'] = train_df['Embarked'].map({'C':0, 'Q':1, 'S':2})

fill_ages = np.zeros((2, 3))
for i in range(0, 2):
    for j in range(0, 3):
        age_i_j = train_df.loc[(train_df['Sex'] == i) & (train_df['Embarked'] == j), 
                               'Age'].dropna()

        fill_ages[i, j] = age_i_j.median()  #这里可以选择均值,还有随机值等

for i in range(0, 2):
    for j in range(0, 3):
        train_df.loc[(train_df['Age'].isnull()) & (train_df['Sex'] == i) &  
                     (train_df['Embarked'] == j), 'Age'] = fill_ages[i, j]

sklearn中处理缺失值的方法

sklearn.preprocessing的Imputer方法可以进行缺失值的处理,可以选择平均数,众数或者中位数来填充缺失的值。

from sklearn.preprocessing import Imputer
import numpy as np

#strategy表示采用何种策略,有mean,median, most_frequent
#axis=0, 表示在咧上面进行操作, axis=1表示在行上面进行操作
imp  = Imputer(missing_values='NaN', strategy='mean', axis=0)
#通过fit以后,得到第一列的均值为(1+7)/2 = 4 ,第二列的均值为11/3,
## 以后进行transform的时候,直接将这些值填充过去就可以了
imp.fit([[1, 2], [np.nan, 3], [7, 6]])

X = [[np.nan, 2], [6, np.nan], [7, 6]]
print(imp.transform(X))

输出结果如下:

[[4.         2.        ]
 [6.         3.66666667]
 [7.         6.        ]]

参考:

数据分析中的缺失值处理

机器学习中如何处理缺失数据? - 马骏的回答 - 知乎

Preprocessing data

原文地址:https://www.cnblogs.com/jiaxin359/p/8594640.html