資料預處理之缺失值插補 — 基於R語言

本文結構:前言——資料介紹——檢查缺失值分佈——缺失值插補(4種方法)——總結

前言:

現實生活中的資料是紛繁雜亂的,收集來的資料有缺失和錄入錯誤司空見慣,所以學習如果處理這些常見問題是每一個資料人必須掌握的技能,俗話說巧婦難為無米之炊,不能很好的處理原始資料會給後來的建模帶來麻煩,甚至引入不必要的偏差和錯誤,資料科學家都熟悉“垃圾進垃圾出”的說法。本文介紹的是資料預處理中非常重要的一步——缺失值處理。

資料介紹:

本文資料來自西南財經大學統計學院李可老師提供的信貸資料。其資料是完好的,共有2萬多條記錄。本文隨機挑選1000條資料,並對其中的貸款額(loan_amnt)和信用等級(grade)隨機選取20個資料點設定為缺失值(NA)。

# 設定工作路徑
setwd('D:\\缺失值處理常見辦法')
# 載入資料集
loandata <- read.csv('loanData.csv', header = TRUE)
# 隨機選取1000條記錄,並將其中部分資料設定為缺失值
set.seed(1)
ind <- sample(nrow(loandata), 1000)
data.sample <- na.omit(loandata)[ind,]     # 確保樣本資料是無缺失的
data.copy <- data.sample                   # 複製資料,為後來的結果做對比操作
data.copy$loan_amnt[sample(nrow(data.copy), 20)] <- NA        #設定缺失值
data.copy$grade[sample(nrow(data.copy), 20)] <- NA            #設定缺失值

檢查缺失值分佈:

所有學過R語言的同學應該都清楚is.na()函式可以檢查資料中是否有缺失值,但R語言還有兩個有趣的包可以幫助我們快速瞭解資料框中的缺失值的分佈情況——mice包和VIM包。

# mice包檢測
require(mice)
summary(data.copy)
md.pattern(data.copy)
# 本例結果(不同抽樣結果不必完全一樣)

圖1

圖1為mice包中md.pattern()函式的輸出結果,’1’代表完好資料,’0’代表缺失值。左側第一列,’963’代表有963條記錄是完全沒有缺失值的,第一個’17’代表有17條資料僅loan_amnt變數存在缺失值,’3’代表有3條記錄在loan_amnt和grade同時存在缺失值。

#VIM包檢測
require(VIM)
aggr_plot <- aggr(data.copy, col = c('blue','red'),numbers = TRUE,sortVars = TRUE, labels=names(data.copy),Cex.axis = .7, gap = 3,Ylab = c("Missing data histogram","Missing value pattern"))

圖2
圖2為VIM包中aggr()函式的輸出結果,它是對缺失值分佈的視覺化。其中手動設定藍色為完好值,紅色為缺失值。

缺失值插補:

1). 處理方法 —- 刪除行/列 (na.action=na.omit())
適用條件:
足夠大資料集 (model doesn’t lose power)
不會引入偏差 (no disproportionate or non-representation of classes)

刪列:不起重要預測作用的變數

2). 處理方法 —- 替換 (mean / median / mode)
適用條件:
不需要非常精確的估算

# 用均值和特定值替換
# 自定義插補函式
impute <- function(x, x.impute){ifelse(is.na(x),x.impute,x)}
impute(data.copy$loan_amnt, mean(ata.copy$loan_amnt))   #均值替換   
impute(data.copy$loan_amnt, 20)        # 特定值替換

3). 最近鄰插補——kNN

# 最近鄰填補缺失值
require(DMwR)
knnOutput <- knnImputation(data.copy[c(-1,-4,-5)]) 
anyNA(knnOutput)
# 將插補值與實際值進行對照
actuals <-data.sample$loan_amnt[is.na(data.copy$loan_amnt)]
predicteds <- knnOutput[is.na(data.copy$loan_amnt),
"loan_amnt"]
# 兩樣本均值檢驗並計算其相似度
t.test(actuals, predicteds)        # 接受差值為0的假設
cor(actuals, predicteds)           # 在粗處理的情況下相似度可以達到63%左右

4). 分類迴歸樹——rpart
相比於kNN,rpart方法可以應用於分類資料

注意點:rpart()建立分類迴歸樹模型

  • 對於分類變數,新增引數:method = “class”
  • 對於數值變數,新增引數:method = “anova”
# rpart填補缺失值
require(rpart)
# 對分類變數的預測建模
class_mod <- rpart(grade ~ ., data =  data.copy[!is.na(data.copy$grade), ][-1],method = "class", na.action = na.omit)
# 對連續變數的預測建模
anova_mod <- rpart(loan_amnt ~ ., data =data.copy[!is.na(data.copy$loan_amnt), ][-1],method = "anova", na.action = na.omit)
# 根據模型進行預測      
grade_pred <- predict(class_mod,data.copy[is.na(data.copy$grade), ], type = 'class')
loan_amnt_pred <- predict(anova_mod,data.copy[is.na(data.copy$loan_amnt), ])
# 將loan_amnt的實際值與預測值對比
actuals <-data.sample$loan_amnt[is.na(data.copy$loan_amnt)] 
predicteds <- loan_amnt_pred
# 檢驗
t.test(actuals, predicteds)        # 接受差值為0的假設
cor(actuals, predicteds)       # 在粗處理的情況下相似度可以達到67%左右

注意:無論是最近鄰還是分類迴歸樹插補法,在預測建模時都不應該包含響應變數。

總結:
對缺失值插值有很多注意和值得研究的地方,本文僅是選取了部分常用的方法,結合R語言,粗略地介紹之。粗糙石磚,還望引玉。