在真實的世界中,缺失數據是經常出現的,並可能對分析的結果造成影響。在R中,經常使用VIM(Visualization and Imputation of Missing values)包來對缺失值進行可視化和插補。在使用VIM繪圖時,有些繪圖函數會對缺失值會自動進行插補。
缺失數據的分類:
- MCAR(完全隨機缺失):若變量的缺失數據與其他任何觀測或未觀測的變量都不相關,則數據為MCAR.。
- MAR(隨機缺失):若變量的缺失數據與其他觀測變量相關,與未觀測變量無關,則數據缺失是隨機缺失。
- NMAR(非隨機缺失):若缺失數據不屬於MCAR和MAR,則數據是非隨機缺失。
大部分處理缺失數據的方法都是假定數據是MCAR或MAR。
一,識別缺失值
R使用NA代表缺失值,NaN(不是一個數)代表不可能的值,符號Inf和-Inf分別代表正無窮和負無窮。
函數is.na()、is.nan()和is.infinite()分別用來識別缺失值,不可能值和無窮值。
函數complete.cases() 可以用來識別矩陣或數據框中的沒有缺失值的行,若每行有一個或多個缺失值,則返回FALSE。注意,complete.cases()僅把NA和Nan識別為缺失值,無窮值(Inf和-Inf)被當作有效值。
二,探索缺失值的模式
在決定如何處理缺失數據前,了解哪些變量有缺失值、數目有多少、是什么組合等信息,是非常有用的。
1,列表顯示缺失值
mice包中的md.pattern()函數可以生成一個以矩陣或數據框形式展示缺失值模式,0表示變量的列中存在缺失值,1則表示沒有缺失值。注意,md.pattern()函數僅把NA識別為缺失值。
md.pattern(x, plot = TRUE)
例如,以VIM包提供的哺乳動物的睡眠數據(sleep,基礎安裝包中還有一個描述葯效的sleep數據集)。
library(VIM) library(mice) data(sleep,package='VIM') md.pattern(sleep, FALSE) BodyWgt BrainWgt Pred Exp Danger Sleep Span Gest Dream NonD 42 1 1 1 1 1 1 1 1 1 1 0 9 1 1 1 1 1 1 1 1 0 0 2 3 1 1 1 1 1 1 1 0 1 1 1 2 1 1 1 1 1 1 0 1 1 1 1 1 1 1 1 1 1 1 0 1 0 0 3 1 1 1 1 1 1 1 0 0 1 1 2 2 1 1 1 1 1 0 1 1 1 0 2 2 1 1 1 1 1 0 1 1 0 0 3 0 0 0 0 0 4 4 4 12 14 38
顯示的結果中,模式是列的組合,第一列表示模式的數量,最后一列表示行中包含缺失值的列的數量,最后一行表示列中缺失值的數量。
比如,對於第一行,缺失值的數量是0,這樣的數據行在數據集中有42個。對於第二行,包含缺失值的列(Dream和NonD 同時缺失)數量是2,這樣的行在數據集中有9個。
2,用圖形探究缺失數據
VIM包提供了大量能可視化缺失值模式的函數,aggr()、marginplot()和scattMiss()。
library(VIM) data(sleep,package='VIM') aggr(sleep,prop=FALSE,numbers=TRUE)
aggr重要參數注釋:
- prob:當為TRUE時,顯示為缺失值的占比;當為FALSE時,顯示為缺失值的數量;
- numbers:是否顯示數值,默認為FALSE,不顯示缺失值的占比或數量。
使用散點圖來可視化兩個變量的異常值:
library(VIM) data(sleep,package='VIM') marginplot(sleep[,c('Gest','Dream')],pch = c(20,1),col=c('darkgray','red','blue'))
對於包含兩個變量的數據點,兩個變量表示一個點(x,y),如果x和y都不包含缺失值,稱作有效點;如果x或x中有一個包含缺失值,叫做單變量缺失,對於單變量缺失,該函數會自動插補;如果x和y都包含缺失值,叫做不可用點。
marginplot重要參數注釋:
- x:包含兩列的數據框,第一列是x軸,第二列是y軸,
- pch:點的形狀,是個雙值的向量,分別用於設置用於顯示包含缺失值/插補值的點的形狀,和有效點的形狀。
- col:向量,用於設置繪圖中使用的顏色。第一個顏色用於繪制有效點的散點圖和箱圖,第二個顏色用於繪制單變量缺失的散點圖和箱圖;第三個圖顏色用於繪制不可用點。
紅色箱圖表示包含插補值之后的分布,灰色箱圖表示有效點的分布。紅色的空心點是插補之后的點。
3,用相關性探索缺失值
用指示變量代替數據集中的數據(1代表缺失,0代表存在),這樣生成的矩陣有時被稱作影子矩陣,求這些指示變量之間的相關性,有助於觀察哪些變量經常一起缺失。
library(VIM) data(sleep,package='VIM') x <- as.data.frame(abs(is.na(sleep))) y <- x[which(apply(x,2,sum)>0)] cor(y) NonD Dream Sleep Span Gest NonD 1.00000000 0.90711474 0.48626454 0.01519577 -0.14182716 Dream 0.90711474 1.00000000 0.20370138 0.03752394 -0.12865350 Sleep 0.48626454 0.20370138 1.00000000 -0.06896552 -0.06896552 Span 0.01519577 0.03752394 -0.06896552 1.00000000 0.19827586 Gest -0.14182716 -0.12865350 -0.06896552 0.19827586 1.00000000
可以看到,Dream和NonD常常一起缺失(r=0.91)。
使用影子矩陣和原始數據之間的相關性,可以探索數據缺失的類型。
cor(sleep,y,use='pairwise.complete.obs') NonD Dream Sleep Span Gest BodyWgt 0.22682614 0.22259108 0.001684992 -0.05831706 -0.05396818 BrainWgt 0.17945923 0.16321105 0.007859438 -0.07921370 -0.07332961 NonD NA NA NA -0.04314514 -0.04553485 Dream -0.18895206 NA -0.188952059 0.11699247 0.22774685 Sleep -0.08023157 -0.08023157 NA 0.09638044 0.03976464 Span 0.08336361 0.05981377 0.005238852 NA -0.06527277 Gest 0.20239201 0.05140232 0.159701523 -0.17495305 NA Pred 0.04758438 -0.06834378 0.202462711 0.02313860 -0.20101655 Exp 0.24546836 0.12740768 0.260772984 -0.19291879 -0.19291879 Danger 0.06528387 -0.06724755 0.208883617 -0.06666498 -0.20443928 Warning message: In cor(sleep, y, use = "pairwise.complete.obs") : 標准差為零
在這個相關系數矩陣中,行是可觀測的變量,列為表示缺失的指示變量。注意,表中的相關系數都不大,表明數據是MCAR的可能性比較小,更可能是MAR。
三,缺失數據的處理
識別缺失數據的數目、分布和模式,有兩個目的:分析生成缺失數據的潛在機制,評價缺失數據對回答實質性問題的影響。具體來講,需要弄清楚以下幾個問題:
- 缺失數據的比例有多大?
- 缺失數據是否集中在少數幾個變量上,抑或廣泛存在?
- 缺失是隨機產生的嗎?
- 缺失數據間的相關性或與可觀測數據之間的相關性,是否可以表明產生缺失值的機制。
回答這些問題將有助於采用合適的方法來處理缺失數據。
- 如果缺失數據集中在幾個相對不重要的變量上,那么可以刪除這些變量。
- 如果有一小部分數據(如小於10%)隨機分布在整個數據集中(MCAR),那么你可以刪除存在缺失數據的行,而只分析數據完整的實例,這樣扔可以得到可靠且有效的結果。
- 如果可以假定數據是MCAR或MAR,那么可以應用多重插補法來獲得有效的結論。
1,推理恢復
根據變量之間的關系來填補或恢復缺失值,通過推理,數據的恢復可能是准確的或近似的。
2,行刪除
把包含一個或多個缺失值的行刪除,稱作行刪除法,或個案刪除(case-wise deletion),大部分統計軟件包默認采用的是行刪除法。
newdata <- mydata[complete.cases(mydata),]
newdata <- na.omit(mydata)
當數據是MCAR(完整的觀測只是全數據集的一個隨機樣本)時,采用行刪除之后,也會得到可靠和有效的結論。
3,簡單插補
簡單插補,也叫均值插補,是用均值,中位數或眾數來替換變量中缺失的值。將初始數據集中的屬性分為數值屬性和非數值屬性來分別進行處理。
- 如果空值是數值型的,就根據該屬性在其他所有對象的取值的平均值來填充該缺失的屬性值;
- 如果空值是非數值型的,就根據統計學中的眾數原理,用該屬性在其他所有對象的取值次數最多的值(即出現頻率最高的值)來補齊該缺失的屬性值。
簡單插補對於非MCAR的數據會產生有偏向的結果,適用於缺失數據的數量較小的數據集。均值插補是在低缺失率下首選的插補方法,缺點是不能反映缺失值的變異性;
四,插補法(MI)
插補法可以在一定程度上減少偏差,常用的插補法是回歸插補、多重插補和熱卡插補。
- 回歸插補,要求變量間存在強的相關性;
- 多重插補(MCMC法),是在高缺失率下的首選插補方法,優點是考慮了缺失值的不確定性;
1,回歸插補
基於完整的數據集,建立回歸方程。對於包含空值的對象,將已知屬性值代入方程來估計未知屬性值,以此估計值來進行填充。當變量不是線性相關時會導致有偏差的估計。
2,多重插補
多重插補(MI)是一種基於重復模擬的處理缺失值的方法,它從一個包含缺失值的數據集中生成一組數據完整的數據集(即不包含缺失值的數據集,通常是3-10個)。每個完整數據集都是通過對原始數據中的缺失數據進行插補而生成的。在每個完整的數據集上引用標准的統計方法,最后,把這些單獨的分析結果整合為一組結果。
多重插補法大致分為三步:
- 為每個空值產生一套可能的插補值,這些值反映了無響應模型的不確定性;每個值都被用來插補數據集中的缺失值,產生若干個完整數據集合。
- 每個插補數據集合都用針對完整數據集的統計方法進行統計分析。
- 對來自各個插補數據集的結果進行整合,產生最終的統計推斷,這一推斷考慮到了由於數據插補而產生的不確定性。該方法將空缺值視為隨機樣本,這樣計算出來的統計推斷可能受到空缺值的不確定性的影響。
R中可以利用Amelia、mice和mi包來執行這些操作。下圖可以幫助理解mice包的操作過程。
函數mice()首先從一個包含缺失數據的數據框開始,然后返回一個包含多個(默認為5個)完整數據集的對象。每個完整數據集都是通過對原始數據框中的缺失數據進行插補而生成的。由於插補有隨機的成分,因此每個完整數據集都略有不同。然后,with()函數可依次對每個完整的數據集應用統計模型(如線性模型或廣義線性模型),最后,pool()函數把這些單獨的分析結果整合為一組結果。最終模型的標准差和p值都准確地反映出由於缺失值和多重插補而產生的不確定性。
library(mice) imp <- mice(data seed=m) fit <- with( imp, lm()) po<- pool(fit) summary(po)
mice()函數如何插補缺失值?
缺失值的插補法通過Gibbs抽樣完成,每個包含缺失值的變量都默認可通過數據集中的其他變量預測的來,於是這些預測方程便可用於預測數據的有效值。該方程不斷迭代直到所有的缺失值都收斂為止。
默認情況下,預測的均值用於替換連續性變量中的缺失數據,而Logistic或多元Logisitcs回歸分別用於替換二值目標變量(兩水平因子)或多值變量(多水平因子)。
mice包中的mice函數:
mice(data, m = 5, method = NULL, defaultMethod = c("pmm", "logreg", "polyreg", "polr"), seed = NA, ...)
重要參數注釋:
- m:多重插補的次數,默認值是5
- method:用於每列插補的算法
- defaultMethod:默認的插補算法
- seed:隨機數種子
3,熱卡填充(Hot deck imputation,或就近補齊)
對於一個包含空值的對象,熱卡填充法在完整數據中找到一個與它最相似的對象,然后用這個相似對象的值來進行填充。不同的問題可能會選用不同的標准來對相似進行判定。該方法概念上很簡單,且利用了數據間的關系來進行空值估計。這個方法的缺點在於難以定義相似標准,主觀因素較多。
參考文檔: