原文:
C#使用拉依达准则(3σ准则)剔除异常数据(.Net剔除一组数据中的奇异值)
1、问题的提出:
电池生产中,遇到一批电池的测量结果数据:
| 电压值 |
电池个数 |
|
电压值 |
电池个数 |
|
电压值 |
电池个数 |
|
电压值 |
电池个数 |
| 0.056 |
1 |
|
4.09 |
1 |
|
4.146 |
17 |
|
4.174 |
13434 |
| 0.321 |
1 |
|
4.094 |
1 |
|
4.147 |
17 |
|
4.175 |
13973 |
| 0.767 |
1 |
|
4.099 |
2 |
|
4.148 |
19 |
|
4.176 |
13339 |
| 0.972 |
1 |
|
4.112 |
1 |
|
4.149 |
23 |
|
4.177 |
12275 |
| 3.098 |
1 |
|
4.119 |
3 |
|
4.15 |
26 |
|
4.178 |
10309 |
| 3.187 |
1 |
|
4.12 |
1 |
|
4.151 |
40 |
|
4.179 |
8376 |
| 3.319 |
1 |
|
4.121 |
1 |
|
4.152 |
50 |
|
4.18 |
6324 |
| 3.526 |
1 |
|
4.122 |
3 |
|
4.153 |
75 |
|
4.181 |
4667 |
| 3.53 |
1 |
|
4.125 |
3 |
|
4.154 |
84 |
|
4.182 |
3340 |
| 3.532 |
1 |
|
4.126 |
2 |
|
4.155 |
100 |
|
4.183 |
2358 |
| 3.54 |
1 |
|
4.127 |
1 |
|
4.156 |
118 |
|
4.184 |
1719 |
| 3.541 |
1 |
|
4.128 |
2 |
|
4.157 |
153 |
|
4.185 |
1199 |
| 3.544 |
1 |
|
4.129 |
3 |
|
4.158 |
173 |
|
4.186 |
839 |
| 3.545 |
2 |
|
4.13 |
2 |
|
4.159 |
248 |
|
4.187 |
622 |
| 3.832 |
1 |
|
4.132 |
2 |
|
4.16 |
335 |
|
4.188 |
417 |
| 3.928 |
1 |
|
4.133 |
2 |
|
4.161 |
419 |
|
4.189 |
304 |
| 3.93 |
1 |
|
4.134 |
4 |
|
4.162 |
540 |
|
4.19 |
170 |
| 3.951 |
1 |
|
4.135 |
1 |
|
4.163 |
731 |
|
4.191 |
124 |
| 3.963 |
1 |
|
4.136 |
5 |
|
4.164 |
962 |
|
4.192 |
77 |
| 3.972 |
1 |
|
4.137 |
4 |
|
4.165 |
1359 |
|
4.193 |
43 |
| 3.973 |
2 |
|
4.138 |
6 |
|
4.166 |
1846 |
|
4.194 |
44 |
| 4.045 |
1 |
|
4.139 |
9 |
|
4.167 |
2621 |
|
4.195 |
25 |
| 4.046 |
1 |
|
4.14 |
2 |
|
4.168 |
3728 |
|
4.196 |
20 |
| 4.079 |
1 |
|
4.141 |
6 |
|
4.169 |
5086 |
|
4.197 |
8 |
| 4.085 |
1 |
|
4.142 |
4 |
|
4.17 |
6822 |
|
4.198 |
9 |
| 4.087 |
1 |
|
4.143 |
6 |
|
4.171 |
8649 |
|
4.199 |
5 |
| 4.088 |
1 |
|
4.144 |
13 |
|
4.172 |
10210 |
|
4.2 |
3 |
| 4.089 |
1 |
|
4.145 |
14 |
|
4.173 |
12072 |
|
|
|
其中,有一部分电池的电压出现过低和过高的情况,并不符合正态分布。
现在需要剔除这些异常的电池数据。
2、方法原理:
3σ准则又称为拉依达准则,它是先假设一组检测数据只含有随机误差,对其进行计算处理得到标准偏差,按一定概率确定一个区间,认为凡超过这个区间的误差,就不属于随机误差而是粗大误差,含有该误差的数据应予以剔除。
在正态分布中σ代表标准差,μ代表均值。x=μ即为图像的对称轴
3σ原则:
数值分布在(μ-σ,μ+σ)中的概率为0.6827
数值分布在(μ-2σ,μ+2σ)中的概率为0.9544
数值分布在(μ-3σ,μ+3σ)中的概率为0.9974
可以认为,Y 的取值几乎全部集中在(μ-3σ,μ+3σ)区间内,超出这个范围的可能性仅占不到0.3%。
3、C#的具体实现:
//定义电压-数量关系的类
public class VoltageCount
{
public Double Voltage { get; set; }
public int CountV { get; set; }
public VoltageCount()
{
}
public VoltageCount(Double voltage, int countV)
{
this.Voltage = voltage;
this.CountV = countV;
}
}
//关键类使用拉依达准则(3σ准则)剔除数据异常
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Photo.QQAA.Net.Helper
{
/// <summary>
/// 使用拉依达准则(3σ准则)剔除数据异常
/// </summary>
public class ExceptionVoltageHelper
{
List<VoltageCount> listVoltageCount;
double average = 0.0;
int _badDataCount = -1;//奇异值个数
/// <summary>
/// 获取奇异值个数
/// </summary>
public int BadDataCount
{
get { return _badDataCount; }
}
public ExceptionVoltageHelper(List<VoltageCount> list)
{
this.listVoltageCount = list;
SetAverage();
}
/// <summary>
/// 取得平均电压值
/// </summary>
/// <returns></returns>
protected double GetAvgVoltage()
{
double avg = 0;
double total = 0;
int allCount = 0;
foreach (VoltageCount vc in listVoltageCount)
{
double v = vc.Voltage;
int c = vc.CountV;
total += v * c;
allCount += c;
}
avg = total / (allCount * 1.0);
return Math.Round(avg, 3, MidpointRounding.AwayFromZero);
}
/// <summary>
/// 平均值
/// </summary>
/// <returns></returns>
void SetAverage()
{
this.average = GetAvgVoltage();
}
/// <summary>
/// 标准差
/// </summary>
/// <returns></returns>
double StandardDeviation()
{
List<double> listDataV = new List<double>();
foreach (VoltageCount vc in this.listVoltageCount)
{
double v = vc.Voltage;
int countV = vc.CountV;
for (int i = 0; i < countV; i++ )
{
listDataV.Add((v - this.average) * (v - this.average));
}
}
double sumDataV = listDataV.Sum();
double std = Math.Sqrt(sumDataV / (listDataV.Count - 1));
return std;
}
public List<VoltageCount> GetGoodList()
{
_badDataCount = 0;
double sd3 = StandardDeviation() * 3;//3倍标准差
List<VoltageCount> listVC = new List<VoltageCount>();
foreach (VoltageCount vc in this.listVoltageCount)
{
if (Math.Abs(vc.Voltage - this.average) <= sd3)
{
listVC.Add(vc);
}
else
{
_badDataCount += vc.CountV;
}
}
return listVC;
}
}
}
4、局限性及注意事项:
本3σ法则仅局限于对正态或近似正态分布的样本数据处理,且适用于有较多组数据的时候。
这种判别处理原理及方法是以测量次数充分大为前提的,当测量次数的情形用准则剔除粗大误差是不够可靠的。因此,在测量次数较少的情况下,最好不要选用准则,而用其他准则。