using System;
|
using System.Linq;
|
|
namespace IStation.WinFrmUI
|
{
|
public class FilterOutliersHelper
|
{
|
/// <summary>
|
/// 根据 标准差 过滤
|
///
|
/// 一、标准差的计算方法
|
/// 1、总体标准差的计算方法:首先计算每个数据与平均值的差值,然后将差值平方,再求平均值,最后取平方根。
|
/// 2、样本标准差的计算方法:与总体标准差类似,但在计算差值平方的平均值时,除以样本容量减1。
|
/// 二、标准差的应用
|
/// 1、数据分布的解释:标准差可以帮助我们了解数据的离散程度。标准差越大,数据越分散;标准差越小,数据越集中。
|
/// 2、异常值的检测:通过计算标准差,我们可以判断是否存在异常值。如果某个数据与平均值的差距超过2个标准差,可以认为该数据是异常值。
|
/// 3、风险评估:在金融领域,标准差常用于衡量投资组合的风险。标准差越大,投资组合的风险越高。
|
/// 三、如何减小标准差
|
/// 1、增加样本容量:样本容量越大,标准差越小,因为更多的数据可以更好地反映总体的特征。
|
/// 2、优化数据收集方法:确保数据的采集过程准确无误,避免数据的偏差和误差。
|
/// 结论:标准差是一种重要的统计量,可以帮助我们理解数据的离散程度和风险。通过计算标准差,我们可以对数据进行解释、分析和评估。在实际应用中,我们可以通过增加样本容量和优化数据收集方法来减小标准差,提高数据的可靠性和准确性。
|
/// </summary>
|
/// <param name="arr"></param>
|
/// <param name="use_STDP">使用总体标准差</param>
|
/// <returns></returns>
|
public static double[] FilterBySTDEV(double[] arr, bool use_STDP)
|
{
|
if (arr == null || arr.Length < 2)
|
{
|
return arr;
|
}
|
|
double std_dev = 0, STDP = 0;
|
|
var arr_count = arr.Length;
|
var arr_avg = arr.Average();
|
STDEV(arr, out std_dev, out STDP);
|
|
|
var arr_filter_std_dev = arr.Where(x => !(Math.Abs(x - arr_avg) > Math.Abs(std_dev * 2))).ToArray();
|
if (arr_filter_std_dev != null && arr_filter_std_dev.Length != arr_count)
|
{
|
STDEV(arr_filter_std_dev, out std_dev, out STDP);
|
}
|
|
var arr_filter_STDP = arr.Where(x => !(Math.Abs(x - arr_avg) > Math.Abs(STDP * 2))).ToArray();
|
if (arr_filter_STDP != null && arr_filter_STDP.Length != arr_count)
|
{
|
STDEV(arr_filter_STDP, out std_dev, out STDP);
|
}
|
|
if (use_STDP)
|
{
|
return arr_filter_STDP;
|
}
|
|
return arr_filter_std_dev;
|
}
|
|
|
|
/// <summary>
|
/// 样本标准差和总体标准差计算
|
/// </summary>
|
/// <param name="arrData">数据数组</param>
|
/// <param name="std_dev">样本标准差</param>
|
/// <param name="STDP">总体标准差</param>
|
public static void STDEV(double[] arrData, out double std_dev, out double STDP) //计算标准偏差
|
{
|
double xSum = 0F;//样本总和
|
double xAvg = 0F;//样本平均值
|
double sSum = 0F;//方差的分子
|
//float tmpStDev = 0F;
|
int arrNum = arrData.Length;//得到样本数量,分母
|
for (int i = 0; i < arrNum; i++)//循环计算得到样本总和
|
{
|
xSum += arrData[i];
|
}
|
xAvg = xSum / arrNum;//计算得到样本平均值
|
for (int j = 0; j < arrNum; j++)//得到方差的分子
|
{
|
sSum += ((arrData[j] - xAvg) * (arrData[j] - xAvg));
|
}
|
std_dev = Convert.ToSingle(Math.Sqrt((sSum / (arrNum - 1))).ToString());//样本标准差
|
STDP = Convert.ToSingle(Math.Sqrt((sSum / arrNum)).ToString());//总体标准差
|
}
|
|
|
}
|
}
|