R筆記–(10)遺漏值處理(Impute Missing Value)

skydome20

2016/06/06

返回主目錄

【如果喜歡,你也可以免費支持 R 系列筆記!】


本篇目錄

  1. 直接移除有遺漏值的資料
  2. 用「平均數」、「第一四分位數」…來填補遺漏值
  3. 用k-Nearest Neighbours填補遺漏值
  4. 用MICE填補遺漏值
  5. 總結

前面幾篇,介紹了一些常用的資料探勘模型。

不過本篇內容比較不太一樣,比較著重在「資料預處理」(或者稱資料清洗)的手法上。

畢竟在資料分析的流程中,其實有60~70%的時間是在進行「資料預處理」。如果沒有好的資料,後續的分析其實就可能會有很大的偏誤。

在「資料預處理」時,我們時常會遇到很多問題需要解決。當然,也有有很多對應的小技巧,可以幫助我們處理這些問題。

而本篇內容,主要針對一個比較重要問題:遺漏值(Missing Value),進行處理!

在R裡面,遺漏值會被表現成NA(not available),而我們可以使用is.na()的函式,確認資料中是否有遺漏值的存在:

tmp <- c(1,5,8,NA,5,NA,6)
is.na(tmp)
## [1] FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE
# 計算遺漏值的個數
sum(is.na(tmp))
## [1] 2

在處理遺漏值時,大多數的人都會「直接移除資料」或是用「平均值來填補遺漏值」,但這樣的做法並不推薦:前者會讓資料減少,後者不會產生任何資訊。

因此在遺漏值處理的手法上,最推崇的就是「k-Nearest Neighbours」或「mice套件」來填補遺漏值。其中,mice的全名為Multivariate Imputation via Chained Equations

兩者的概念很簡單,都是先用資料探勘的方法「模擬遺漏值」後,再進行「填補(impute)」。詳情會在下面介紹。


我們先使用iris的資料集,讓資料中隨機產生遺漏值,再來練習剛剛介紹的處理手法:

require(missForest) # prodNA() function
## Warning: package 'missForest' was built under R version 3.4.4
## Warning: package 'itertools' was built under R version 3.4.4
# 在iris資料內,隨機產生10%的遺漏值
data <- prodNA(iris, noNA = 0.1)
# 可以注意到,資料裡面有NA的存在,代表Not-Available(遺漏值)
head(data)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1          5.1         3.5          1.4         0.2    <NA>
## 2          4.9          NA          1.4         0.2  setosa
## 3          4.7         3.2          1.3         0.2  setosa
## 4          4.6         3.1          1.5         0.2    <NA>
## 5          5.0         3.6          1.4         0.2  setosa
## 6           NA         3.9          1.7         0.4  setosa

接著介紹剛剛提及的四種處理遺漏值的手法:


1. 直接移除有遺漏值的資料

# 當一筆資料是完整的,回傳TRUE;當一筆資料有遺漏值,回傳FALSE
complete.cases(data)
##   [1] FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE  TRUE FALSE  TRUE FALSE
##  [12] FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE
##  [23] FALSE FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
##  [34] FALSE  TRUE  TRUE FALSE  TRUE FALSE  TRUE  TRUE FALSE  TRUE FALSE
##  [45]  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE
##  [56]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE FALSE
##  [67] FALSE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE
##  [78]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE
##  [89]  TRUE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE  TRUE FALSE
## [100]  TRUE FALSE FALSE  TRUE  TRUE FALSE  TRUE  TRUE  TRUE FALSE  TRUE
## [111] FALSE  TRUE FALSE  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE  TRUE
## [122]  TRUE FALSE  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE FALSE  TRUE
## [133]  TRUE  TRUE  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE
## [144] FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
# 移除有遺漏值的資料
rm.data <- data[complete.cases(data), ]

可是這麼做不太好,因為會造成資訊損失(information loss)。

所以我們常會採取「填補遺漏值」的手法,也就是下面即將介紹的!


2. 用「平均數」、「第一四分位數」…來填補遺漏值

# 以下用平均數,來填補某一欄位的遺漏值
mean.data <- data

mean.1 <- mean(mean.data[, 1], na.rm = T)  # 第一欄位的平均數
na.rows <- is.na(mean.data[, 1])           # 第一欄位中,有遺漏值存在的資料

# 用第一欄位的平均數,填補第一欄位的遺漏值
mean.data[na.rows, 1] <- mean.1

3. 用K-Nearest Neighbours填補遺漏值

K-Nearest Neighbours(KNN)運用在遺漏值填補上的想法很簡單:

現在有一群學生的成績,包含國文、數學、自然,但老師不小心弄丟小明的國文考卷,於是小明的「國文」分數是遺漏值。

如果在不重考的狀況下,我們要給小明一個分數,該怎麼做?

KNN的概念告訴我們,應該先看小明「數學和自然」的分數,看和哪些同學(K位)很相近,然後再拿那些同學(K位)的國文分數,取平均或加權平均(或是其他手法)後,當作小明的分數來填補。

一句話概括:「就是找和自己很像的K個鄰居,然後從他們身上複製自己所沒有的東西。」

這就是用KNN來填補遺漏值的想法。

require(DMwR)
## Warning: package 'DMwR' was built under R version 3.4.4
imputeData <- knnImputation(data)
head(imputeData)
##   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1     5.100000    3.500000          1.4         0.2  setosa
## 2     4.900000    3.241985          1.4         0.2  setosa
## 3     4.700000    3.200000          1.3         0.2  setosa
## 4     4.600000    3.100000          1.5         0.2  setosa
## 5     5.000000    3.600000          1.4         0.2  setosa
## 6     5.295674    3.900000          1.7         0.4  setosa

4. 用MICE填補遺漏值

在MICE裡面,提供了很多資料探勘的模型(linear regression, logistic regression, cart, random forest, boostrap……),來針對遺漏值進行預測!

概念很簡單:現在我們有欄位V1,V2,V3……Vn,每個欄位裡面都有遺漏值。

當我們要填補V1的遺漏值時,就先把V2,V3……Vn的欄位當作自變數(X),把V1當作應變數(Y),並且進行建模,然後用預測的結果來填補V1的遺漏值。

同理,針對V2,就用V1,V3……Vn建模,然後用預測的結果來填補V2的遺漏值。

(由於這個函式,背後有使用Gibbs sampling(一種抽樣手法)。所以,即使使用某個模型進行遺漏值填補,也會因為抽樣手法,造成最後填補的結果有些許不同)

require(mice)
## Warning: package 'mice' was built under R version 3.4.4
mice.data <- mice(data,
                  m = 3,           # 產生三個被填補好的資料表
                  maxit = 50,      # max iteration
                  method = "cart", # 使用CART決策樹,進行遺漏值預測
                  seed = 188)      # set.seed(),令抽樣每次都一樣

# 原始資料(有遺漏值)
data

# 填補好的資料:因為m=3,所以會有三個填補好的資料集,可以用以下方式取出

complete(mice.data, 1) # 1st data
complete(mice.data, 2) # 2nd data
complete(mice.data, 3) # 3rd data

(由於上面資料集龐大,故在此不顯示出來!)

現在,我們可以任取其中一個「填補好的資料」,來進行後續的建模了!

# e.g. 拿第二個資料,作為我後續分析的資料
df <- complete(mice.data, 2)
head(df)
# 然後以df進行線性迴歸、類神經網路、主成份分析...等等

總結

在資料預處理時,「遺漏值處理」是很重要的步驟,最好還是選擇「填補遺漏值」的方式,才不會造成資訊損失。

在R裡面,其實有提供很多強大的套件,可以幫我們處理遺漏值!

本篇只簡單介紹mice套件,網路上有神人整理出五種處理遺漏值的強大套件,裡面都有詳細的範例:Tutorial on 5 Powerful R Packages used for imputing missing values,有興趣的話可以參考!

It’s still a long way to go~