批量数据采集过程中方差的计算

2020/09/28 20:12

批量数据采集过程中方差的计算

最近项目用需要判断开始数据是否稳定,即采集到的数据是否符合期望,我用方差来判断采集到的数据是否稳定。有两种判断方法:第一种是数据不断的进来,我累积的进行方差计算;第二钟是利用滑动窗口的思想,数据个数达到窗口大小时计算方差值,采用循环数组的模式来实现此功能。

第一种实现方法就是采用迭代式的思想进行方差计算。我实在网上看到一位大神的博客中有对此方法的描述,他用matlab代码进行了说明,,我用C语言实现了;下面附上代码:
[cpp] view plain copy

    double GetVariance(uint64_t value)  
    {  
        static uint8_t cnt = 0;  
        static double Var = 0;  
        static double Esp = 0;  
        double TempValue = 0;  
          
        cnt = cnt + 1;  
        if(cnt == 1)  
        {  
            Var = 0;  
            Esp = value;  
            return Var;  
        }  
        TempValue = value - Esp;  
        Esp = (value + Esp*(cnt - 1))/cnt;   
        Var = Var + TempValue*(value - Esp);  
        return (Var/cnt);  
    } 
这样在程序中不断调用该函数即可迭代式的计算出方差,而不需要知道数据的个数。
第二种方法是采用滑动窗口的思想,这里需要说明一下,我做的时候有两种情况,一种是窗口不动,数据不断前移,FIFO,这种实现起来最简单;还有一种情况是窗口向前移动,这种实现起来就比较复杂了,我用单步调试好多次,才搞清楚之间的区别。
(1)窗口不动,数据前移:

[cpp] view plain copy

    double Function(uint16_t value)  
    {  
        static uint8_t cnt=0;  
        static uint8_t len=7;  
        static uint16_t sample[7]={0};  
        uint8_t i=0;  
        double var;  
        if(cnt < len)  
        {  
            sample[cnt++] = value;  
            return 0;  
        }  
        else  
        {  
            for(;i+1<cnt;i++)  
            {  
                sample[i]=sample[i+1];  
            }  
            sample[i]=value;  
            var=Variance(sample,7);  
    }  
    }  
其中 Variance()是我写的计算方差函数,这样就实现了滑动计算数据方差值。
(2)窗口前移,这种实现数据的滑动,设定好窗口大小后,按照FIFO原则,数据不断进入出去,但是这种实现数据滑动后对计算方差增加了难度,这里只说出如何实现窗口向前滑动的代码:
[cpp] view plain copy

    void Function(uint16_t value)  
    {  
        static uint8_t cnt=0;  
        static uint8_t len=7;  
        static uint8_t index=0;  
        static int order[7]={0};  
        static int sample[7]={0};  
        uint8_t i=0;  
          
        sample[index] = value;  
        if(cnt < len)  
        {  
            cnt++;  
        }  
        else  
        {  
            for(i=0;i<cnt;i++)  
            {  
                if(order[i] == index)  
                break;  
            }  
            for(;i+1<cnt;i++)  
            {  
                order[i]=order[i+1];  
            }  
        }  
          
        order[cnt-1] = index;  
        index=(1+index)%len;  
    }  


最后把计算方差的函数Varanice()代码列出来:
[cpp] view plain copy

    double Variance(uint16_t data[], uint8_t n)  
    {  
        double mean = 0, divisor;  
        uint16_t sum = 0,Varian = 0;  
        uint8_t i;  
      
        for(i=0;i<n;i++)  
        {  
            sum = sum + data[i];  
        }  
        mean = sum/n;  
        for(i=0;i<n;i++)  
        {  
            Varian = Varian + pow(data[i]-mean,2);  
        }  
          
        /*程序中divisor是自由度,20是小样本判断的一个标准。如果是小样本的话,约束较大,
            自由度就要减一;如果是大样本的话,自由度为样本个数。*/  
        if(n<20)  
        {  
            divisor = n-1;  
        }     
        else  
        {  
            divisor = n;  
        }  
        return (Varian/divisor);  
          
    } 
以上代码如有错误还望指正,共同进步

免费直播

    精选课程 更多

    注册电脑版

    版权所有 2003-2020 广州环球青藤科技发展有限公司