Shuxia Ning
2024-11-06 adf8dc1c7cae1b12f486dcdb3d7daf4a5a59ec52
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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());//总体标准差
        }
 
 
    }
}