如何用插值法补齐缺失的数据

在我做的大气污染报表系统中,由于原始数据缺失,经常出现一些负数或者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是一门艺术!思维转换,才能发挥出语言的最大功能。当然这需要长时间的锻炼。 

你可能感兴趣的:(大数据)