Ⅰ 幾種常見的缺失數據插補方法
(一)個案剔除法(Listwise Deletion)
最常見、最簡單的處理缺失數據的方法是用個案剔除法(listwise
deletion),也是很多統計軟體(如SPSS和SAS)默認的缺失值處理方法。在這種方法中如果任何一個變數含有缺失數據的話,就把相對應的個案從分析中剔除。如果缺失值所佔比例比較小的話,這一方法十分有效。至於具體多大的缺失比例算是「小」比例,專家們意見也存在較大的差距。有學者認為應在5%以下,也有學者認為20%以下即可。然而,這種方法卻有很大的局限性。它是以減少樣本量來換取信息的完備,會造成資源的大量浪費,丟棄了大量隱藏在這些對象中的信息。在樣本量較小的情況下,刪除少量對象就足以嚴重影響到數據的客觀性和結果的正確性。因此,當缺失數據所佔比例較大,特別是當缺數據非隨機分布時,這種方法可能導致數據發生偏離,從而得出錯誤的結論。
(二)均值替換法(Mean Imputation)
在變數十分重要而所缺失的數據量又較為龐大的時候,個案剔除法就遇到了困難,因為許多有用的數據也同時被剔除。圍繞著這一問題,研究者嘗試了各種各樣的辦法。其中的一個方法是均值替換法(mean
imputation)。我們將變數的屬性分為數值型和非數值型來分別進行處理。如果缺失值是數值型的,就根據該變數在其他所有對象的取值的平均值來填充該缺失的變數值;如果缺失值是非數值型的,就根據統計學中的眾數原理,用該變數在其他所有對象的取值次數最多的值來補齊該缺失的變數值。但這種方法會產生有偏估計,所以並不被推崇。均值替換法也是一種簡便、快速的缺失數據處理方法。使用均值替換法插補缺失數據,對該變數的均值估計不會產生影響。但這種方法是建立在完全隨機缺失(MCAR)的假設之上的,而且會造成變數的方差和標准差變小。
(三)熱卡填充法(Hotdecking)
對於一個包含缺失值的變數,熱卡填充法在資料庫中找到一個與它最相似的對象,然後用這個相似對象的值來進行填充。不同的問題可能會選用不同的標准來對相似進行判定。最常見的是使用相關系數矩陣來確定哪個變數(如變數Y)與缺失值所在變數(如變數X)最相關。然後把所有個案按Y的取值大小進行排序。那麼變數X的缺失值就可以用排在缺失值前的那個個案的數據來代替了。與均值替換法相比,利用熱卡填充法插補數據後,其變數的標准差與插補前比較接近。但在回歸方程中,使用熱卡填充法容易使得回歸方程的誤差增大,參數估計變得不穩定,而且這種方法使用不便,比較耗時。
(四)回歸替換法(Regression Imputation)
回歸替換法首先需要選擇若干個預測缺失值的自變數,然後建立回歸方程估計缺失值,即用缺失數據的條件期望值對缺失值進行替換。與前述幾種插補方法比較,該方法利用了資料庫中盡量多的信息,而且一些統計軟體(如Stata)也已經能夠直接執行該功能。但該方法也有諸多弊端,第一,這雖然是一個無偏估計,但是卻容易忽視隨機誤差,低估標准差和其他未知性質的測量值,而且這一問題會隨著缺失信息的增多而變得更加嚴重。第二,研究者必須假設存在缺失值所在的變數與其他變數存在線性關系,很多時候這種關系是不存在的。
(五)多重替代法(Multiple Imputation)
多重估算是由Rubin等人於1987年建立起來的一種數據擴充和統計分析方法,作為簡單估算的改進產物。首先,多重估算技術用一系列可能的值來替換每一個缺失值,以反映被替換的缺失數據的不確定性。然後,用標準的統計分析過程對多次替換後產生的若干個數據集進行分析。最後,把來自於各個數據集的統計結果進行綜合,得到總體參數的估計值。由於多重估算技術並不是用單一的值來替換缺失值,而是試圖產生缺失值的一個隨機樣本,這種方法反映出了由於數據缺失而導致的不確定性,能夠產生更加有效的統計推斷。結合這種方法,研究者可以比較容易地,在不舍棄任何數據的情況下對缺失數據的未知性質進行推斷。NORM統計軟體可以較為簡便地操作該方法
Ⅱ 如何用線性插值法補齊缺失數據
在我做的大氣污染報表系統中,由於原始數據缺失,經常出現一些負數或者0的大氣濃度,導致最後生成的曲線很醜,會畫到水平軸以下。將這些錯誤的數據當錯缺失數據處理,需要採取一定的手段填充。缺失的數據採取插值法填充,這一點早就確定下來,但在如何實現上卻困擾很久。
將原始問題簡化一下。比如有這樣一組數據。
ID so co1
1 0.1 0.1
2 0 0.2
3 0.2 0
4 0 0
5 0 0.4
6 0.1 0.5
插值法計算方法如下:(也可以不使用這兩個步驟,只要最後的結果一致就行)
步驟一:計算缺失值上下的已知值間的斜率:
k = (b2 - b1)/(n + 1) n 為缺失數據的個數
步驟二:計算對應的缺失值
a(i) = b1 + k * i
經過處理後,得到的數據是這樣的:
1 0.10 0.10
2 0.15 0.20
3 0.20 0.27
4 0.17 0.33
5 0.13 0.40
6 0.10 0.50
我最初的想法是:在sql語句中用for循環來做。逐條地檢查每個數值,如果是0,那麼獲取它的前一個記錄的值b1,然後再繼續向後遍歷,獲取後面一個非0的值b2,計算這兩個非0數據之間的距離n,之後再用插值法將缺失的數據計算出來,並update到b1和b2之間的每一個值。按照這個思路,很麻煩,比如遍歷過程中如何獲取前一個數值?出現0的時候,如何記錄出現多少個0?for循環經過後,再如何update之前的數值? 被這些問題困擾很久!
在論壇上發帖解決,解決的辦法很受啟發。
1. 創建一個函數
ALTER FUNCTION FUN_CO(@ID INT) RETURNS DECIMAL(18, 3) AS BEGIN DECLARE @NUM1 NUMERIC(19,2),@ID1 INT,@NUM2 NUMERIC(19,2),@ID2 INT SELECT TOP 1 @ID1=ID , @NUM1=CO FROM APRECORD WHERE ID<=@ID AND CO<>0 ORDER BY ID DESC SELECT TOP 1 @ID2=ID , @NUM2=CO FROM APRECORD WHERE ID>=@ID AND CO<>0 ORDER BY ID ASC IF @ID2<>@ID1 RETURN @NUM1+(((@NUM2-@NUM1)/(@ID2-@ID1))*(@ID-@ID1)) RETURN @NUM1 END
2. 更新資料庫
UPDATE APRECORD SET CO=DBO.FUN_CO(ID) WHERE DAYTIME >= @BDT AND DAYTIME < @EDT
在這個解決方案中,首先查找到缺失的數據,也就是值為0的數據,然後向前查找非0數據@NUM1,以及它的編號@ID1,向後查找非0的數據@NUM2. 以及編號@ID2。也就是步驟一。然後用公式計算出填充的數據。將上述過程保存在一個函數中,在存儲過程中調用。甚至不用for循環之類。
---------------------------------------------------------------------------------------
啟示:
1. 明確問題,記錄下來,逐步地尋求解決方案。而不是全憑腦袋空想。腦袋很容易遺漏一些因素,而且大多數時候沒什麼條理,跳躍性太強。解決問題需要方法學。
2. 在sql下思考。用for循環什麼的,還處於靜態語言的思維模式之下。sql是一門藝術!思維轉換,才能發揮出語言的最大功能。當然這需要長時間的鍛煉。