原理参考:https://wenku.baidu.com/view/90cc05a7c8d376eeafaa3151.html
格拉布斯(Grubbs)准则法就是剔除数据集中偏离较远的数据,可以减少异常值对总体数据的影响。
#include
#include
#include
#include
#include
using namespace std;
// 格拉布斯表
double table[] = {0.0, 0.0, 0.0, 1.153,1.463,1.672,1.822,1.938,2.032,2.110,2.176,
2.234,2.285,2.331,2.371,2.409,2.443,2.475,2.501,2.532,2.557,
2.580,2.603,2.624,2.644,2.663,2.681,2.698,2.714,2.730,2.745,
2.759,2.773,2.786,2.799,2.811,2.823,2.835,2.846,2.857,2.866,
2.877,2.887,2.896,2.905,2.914,2.923,2.931,2.940,2.948,2.956,
2.943,2.971,2.978,2.986,2.992,3.000,3.006,3.013,3.019,3.025,
3.032,3.037,3.044,3.049,3.055,3.061,3.066,3.071,3.076,3.082,
3.087,3.092,3.098,3.102,3.107,3.111,3.117,3.121,3.125,3.130,
3.134,3.139,3.143,3.147,3.151,3.155,3.160,3.163,3.167,3.171,
3.174,3.179,3.182,3.186,3.189,3.193,3.196,3.201,3.204,3.207};
// 结构体数据结构
struct data_sort
{
double data; // 原始数据
int id; // 数据对应ID,便于回查原始数据列表
};
// 排序法则,其中:< 升序 >降序
bool comparison(data_sort a,data_sort b)
{
return a.data < b.data ;
}
/**
* @brief My_Grubbs 格拉布斯剔除法
* @param data 待处理数据
* @return
*/
bool My_Grubbs(vector<data_sort> &data)
{
sort(data.begin(), data.end(), comparison);
// 计算平均值
double data_sum = 0;
for(int i=0; i<data.size(); i++)
{
data_sum += data.at(i).data;
}
double data_ave = data_sum/data.size(); // 平均值
// 计算标准差
data_sum = 0;
for(int i=0; i<data.size(); i++)
{
data_sum += pow((data.at(i).data - data_ave), 2);
}
double data_s = sqrt(data_sum/(data.size() - 1)); // 标准差
if(abs(data_ave - data.at(0).data) > abs(data.at(data.size()-1).data - data_ave)) // 当最小值与均值大于最大值与均值
{
if(abs(data.at(0).data - data_ave)/data_s > table[3]) // 满足Gn大于Gp(n)时,为异常值,剔除最小值
{
data.erase(data.begin()); // 剔除最小值
My_Grubbs(data); // 进行递归处理
}
else // 条件满足,可以结束
{
return true;
}
}
else if(abs(data_ave - data.at(0).data) < abs(data.at(data.size()-1).data - data_ave)) // 当最大值与均值大于最小值与均值
{
if(abs(data.at(data.size()-1).data - data_ave)/data_s > table[data.size()-1]) // 满足Gn大于Gp(n)时,为异常值,剔除最大值
{
data.erase(data.begin()+data.size()-1); // 剔除最大值
My_Grubbs(data); // 进行递归处理
}
else // 条件满足,可以结束
{
return true;
}
}
else // 当最大值与均值等于最小值与均值
{
if(abs(data.at(0).data - data_ave)/data_s > table[3]) // 满足Gn大于Gp(n)时,为异常值,剔除最大值和最小值
{
data.erase(data.begin()); // 剔除最小值
data.erase(data.begin() + data.size()-1); // 剔除最大值
My_Grubbs(data); // 进行递归处理
}
else // 条件满足,可以结束
{
return true;
}
}
}