數據預處理之缺失值的處理


 

缺失值的類型

首先對數據的變量(特征)按照缺失和不缺失進行分類:不含有缺失值的變量稱為完全變量,含有缺失值的變量稱為非完全變量。

缺失值的類型分為三種:完全隨機缺失,隨機缺失和非隨機缺失。

完全隨機缺失: 缺失的變量和其余的變量沒有關系。比如”家庭住址“這個信息,和”身高“等其余的變量沒有關系。

隨機缺失: 缺失的變量和完全變量存在一定的關系。假如“學歷”中不含缺失值,“收入”和它有關,那么“收入”為隨機缺失。

非隨機缺失:缺失的變量和非完全變量存在一定的關系。

根據上面變量的分類,其實我們已經大致可以想出來一些處理缺失值的方法了:比如對於完全隨機缺失,我們可以選擇丟棄或者是依靠變量自身未缺失值的信息(均值、方差)進行補全。 而對於隨機缺失,我們可以利用完全變量的信息來進行補全。

 

數據處理的方法

  總的來說,在處理缺失值的時候我們可以采用三種方法,第一種是不作處理,這個很簡單,把缺失值放在那里就可以了。 第二種方法是進行刪除操作。 第三種方法就是進行數據的補全操作。

刪除操作

當某個特征上面的數據缺失太大的時候,直接將這個特征刪除了。

而當特征上面的缺失值很少的時候,比如只有幾個缺失值的時候,可以考慮把包含這些缺失值的元組進行刪除。

補全操作

實際當中用的最多的還是補全操作,補全操作有很多種,按照參考文章一的划分有很多種,可以看原文查看具體的類型,這里我只介紹自己目前明白的幾種:

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM