1. 程式人生 > >如何用插值法補齊缺失的資料

如何用插值法補齊缺失的資料

在我做的大氣汙染報表系統中,由於原始資料缺失,經常出現一些負數或者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<[email protected] AND CO<>0 ORDER BY ID DESC SELECT TOP 1 @ID2=ID , @NUM2=CO FROM APRECORD WHERE ID>

[email protected] AND CO<>0 ORDER BY ID ASC IF @ID2<>@ID1 RETURN @NUM1+(((@[email protected])/(@[email protected]))*(@[email protected])) 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是一門藝術!思維轉換,才能發揮出語言的最大功能。當然這需要長時間的鍛鍊。