zoukankan      html  css  js  c++  java
  • 数据预处理之缺失值的处理

    缺失值的类型

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

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

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

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

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

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

    数据处理的方法

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

    删除操作

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

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

    补全操作

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

    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

  • 相关阅读:
    数据表与简单Java类(多对多的关系)
    数据表与简单java类(一对多的关系)
    微信二次开发SDK使用教程--手机朋友圈评论删除任务反馈通知服务端
    微信二次开发SDK使用教程--手机检测到有人评论/删除朋友圈通知服务端
    微信二次开发SDK使用教程--手机检测到有人点赞/取消点赞通知服务端
    微信二次开发sdk使用教程--手机上删除朋友圈通知服务端
    微信二次开发sdk使用教程--手机上发送了朋友圈通知服务端
    微信二次开发SDK教程--上传手机客户端上微信的二维码给服务端
    微信开发SDK使用教程--手机微信个人号移除好友通知服务端
    微信开发SDK使用教程--手机微信个人号新增好友通知服务端
  • 原文地址:https://www.cnblogs.com/jiaxin359/p/8594640.html
Copyright © 2011-2022 走看看