教你用MSChart控件繪制正態分布圖形。


      一年多的“潛伏”也算是深資“特務”了,長時間看別人的博客,自己卻沒有寫點東東,對不起那些園中勞碌的人。今天終於可以“洗牌”了做正常勞苦大眾。那也得感謝是項目交付期,有了“空擋”可以寫點什么,讓大家拍磚。

      今天主講是的繪制正態分布圖形所用的質量指標公式的,不注重講MSChart圖形控件的用法,MSChart圖形控件博園中有很多實例。正態分布圖形所用的質量指標如下:USL(下規格線簡稱:下限)、USL(上限)、SIGMA(西格瑪)、XBAR(平均值)、SAMPLE DATA(樣本數據)、Zoom Multiple(縮放倍數)、Most Precision(最大精度)。

  1. Most Precision:最大精度,即小數點后面的位數長度。
    View Code
     1         /// <summary>
     2         /// 獲取數據序列的最大精度 (即小數點后面的位數長度)
     3         /// </summary>
     4         /// <param name="sampleData">樣本數據</param>
     5         /// <returns></returns>
     6         public static int GetMostPrecision(List<decimal> sampleData)
     7         {
     8             if (sampleData == null || sampleData.Count == 0)
     9             {
    10                 return 0;
    11             }
    12 
    13             int mostPrecision = 0;
    14             int tempValue = 0;
    15 
    16             foreach (decimal value in sampleData)
    17             {
    18                 string data = Math.Abs(value).ToString();
    19                 int dateLength = data.Length;
    20                 int dotIndex = data.IndexOf(".");
    21 
    22                 if (dotIndex > 0)
    23                 {
    24                     tempValue = dateLength - (dotIndex + 1);
    25                 }
    26 
    27                 if (tempValue > mostPrecision) //取更大的精度
    28                 {
    29                     mostPrecision = tempValue;
    30                 }
    31             }
    32 
    33             return mostPrecision;
    34         }
  2. Zoom Multiple:縮放倍數,為了增加圖形邊沿線的平滑度。
    View Code
     1         /// <summary>
     2         /// 縮放倍數
     3      /// </summary>
     4        /// <param name="mostPrecision"></param>
     5        /// <returns></returns>
     6         private static decimal ZoomMultiple(ref int mostPrecision)
     7         {
     8             decimal zoomMultiple = (decimal)Math.Pow(10, mostPrecision - 1);
     9 
    10             if (mostPrecision <= 2) //保證精度大於二的數據序列圖形的平滑
    11             {
    12                 mostPrecision = 4;
    13                 zoomMultiple = 100;
    14             }
    15 
    16             return zoomMultiple;
    17         }
  3. SAMPLE DATA:樣本數據是概率運算里的一個概念。隨機抽取的部分用於計算出性能優良的數量。
  4. XBAR:這個大家好理解,也很好計算。即是所有樣本數據之和的平均值。
    View Code
    1 double xbar = Math.Round(sampleData.Average(), mostPrecision);
  5. SIGMA:是一個希臘字母σ的中文譯音,在統計學中,代表標准偏差,用來對過程變異進行測量。
    View Code
     1         /// <summary>
     2         /// 計算Sigma
     3         /// </summary>
     4         /// <param name="sampleData">樣本數據</param>
     5         /// <param name="xbar">平均值</param>
     6         /// <returns></returns>
     7         public static double CalculateSigma(List<decimal> sampleData, double xbar)
     8         {
     9             double sigma = 0;
    10             int sampleCount = sampleData.Count;
    11             double powSum = 0;
    12 
    13             if (sampleData == null || sampleCount <= 2
    14 ) //樣本個數大於2計算才有意思
    15             {
    16                 return sigma;
    17             }
    18 
    19             foreach (double value in sampleData)
    20             {
    21                 powSum += Math.Pow(value - xbar, 2); //樣本值減去均值2的次冪相加。
    22             }
    23 
    24             sigma = Math.Sqrt(powSum / (sampleCount - 1));
    25 
    26             return sigma;
    27         }
  6. USL和LSL一般是抽樣人員事先設置好的,也可以用公式得到:
    View Code
    1 double usl = xbar + 3 * sigma;//均值加3sigma
    2 double lsl = xbar - 3 * sigma;//均值減3sigma

       上面是正態分布圖所用到的指標計算公式或方法,公式的解析詳情http://zhidao.baidu.com/question/86348249.html?an=0&si=5下面該介紹正態分布的公式或方法,至於MSChart樣式設置略講,如有需要聯系我kingzheng@yeah.net

     首先清除圖表Series集合上的數據點:

1 chart.Series[serieIndex].Points.Clear();

     X軸正、負界限以及正態公式系數:

1 int positiveLimit = (int)((xbar + 6 * sigma) * zoomMultiple); //X軸的正界限
2 int minusLimit = (int)((xbar - 6 * sigma) * zoomMultiple); //X軸的負界限
3 double coefficient = Math.Round(1 / Math.Sqrt(2 * Math.PI) / sigma, mostPrecision); //系數;如果計算需要精確,就不要四舍五入;建議:為了提高運算效率要四舍五入。

     根據公式生成正態圖形所需要的數據點:

 1 List<double> xValues = new List<double>();
 2 List<double> yValues = new List<double>();
 3  
 4 for (int x = minusLimit; x <= positiveLimit; x++)
 5        {
 6        //x軸縮小zoomMultiple倍x每隔1/zoomMultiple變化曲線變平滑
 7          double xValue = x / zoomMultiple;
 8          double yValue = coefficient * Math.Exp(Math.Pow((xValue - xbar), 2) / (-2 * Math.Pow(sigma, 2)));
 9           xValue = Math.Round(xValue, mostPrecision);
10           yValue = Math.Round(yValue, mostPrecision);
11            if (yValue > 0.0001)//可設為yValue > 0
12              {
13                 xValues.Add(xValue);
14                 yValues.Add(yValue);
15              }
16      }
17 
18 //為MSChart綁定數據值
19  chart.Series[serieIndex].Points.DataBindXY(xValues, yValues);

     為了確保圖形顯示完全,調整X和Y軸的最大值和最小值刻度:

 1  if (yValues.Count > 0)
 2      {
 3         yAxisMax = 0;
 4         return;
 5 
 6      }
 7 //將Y軸最大值放大倍作為
 8        double yMax = Math.Round(yValues.Max() * 1.1, args.MostPrecision);
 9        double xMin = xValues.Min();           
10        double xMax = xValues.Max();
11        double yMin = yValues.Min();
12        yAxisMax = yValues.Max();
13 
14     if (xMin > lsl)
15       {
16         xMin = lsl;
17       }
18     if (xMax < usl)
19       {
20        xMax = usl;
21      }
22 //設置軸值x軸加減極大極小值的1/zoomMultiple倍是為了圖形能全部繪制出來
23 chart.ChartAreas[0].AxisX.Minimum = (double)Math.Round(xMin - xMin * 1 / zoomMultiple, mostPrecision);
24 chart.ChartAreas[0].AxisX.Maximum = (double)Math.Round(xMax + xMax * 1 / zoomMultiple, mostPrecision);
25 chart.ChartAreas[0].AxisY.Minimum = (double)Math.Round(yMin, mostPrecision);
26 chart.ChartAreas[0].AxisY.Maximum = (double)Math.Round(yMax, mostPrecision);

       分別添加XBAR、USL、LSL閾值限函數如下:

View Code
 1         /// <summary>
 2         /// 添加閾值線
 3      /// </summary>
 4         /// <param name="chartArea">圖形Area</param>

 5         /// <param name="lineName">在線顯示的名子</param>
 6         /// <param name="lineOffset">線在圖上的位置</param>
 7         /// <param name="lineWidth">線寬</param>
 8         /// <param name="lineColor">線的顏色</param>
 9         public void AddStripLine(ChartArea chartArea, string lineName, double lineOffset, double lineWidth, Color lineColor)
10         {
11             StripLine stripLine = new StripLine
12             {
13                 BackColor = lineColor,
14                 StripWidth = lineWidth,
15                 BackHatchStyle = ChartHatchStyle.DarkVertical,
16                 Text = lineName,
17                 TextAlignment = StringAlignment.Far,
18                 TextLineAlignment = StringAlignment.Center,
19                 IntervalOffset = lineOffset
20             };
21 
22             chartArea.AxisY.StripLines.Add(stripLine);
23         }

      最后是根據樣本值重置X軸的最大和最小刻度

View Code
 1         /// <summary>
 2         /// 根據sampleData的最大和最小值重設X軸的最大和最小刻度
 3       /// </summary>
 4         /// <param name="queueValue"></param>
 5         public static void ResetAxisBySampleData(List<decimal> sampleData, Chart chart)
 6         {
 7             if (sampleData == null || sampleData.Count <= 0)
 8             {
 9                 SwapValue(chart);
10                 return;
11             }
12 
13             double max = (double) sampleData.Max();
14             double min = (double) sampleData.Min();
15             double xMax = chart.ChartAreas[0].AxisX.Maximum;
16             double xMin = chart.ChartAreas[0].AxisX.Minimum;
17 
18             if (xMin > xMax)
19             {
20                 chart.ChartAreas[0].AxisX.Minimum = min;
21                 chart.ChartAreas[0].AxisX.Maximum = max;
22             }
23         }

以上是正態分布圖所用到的指標和函數,正態直方圖所用到的指標和函數下次再講,時間倉促,寫的不細。如有不明的請發郵件,我們一起探討。Mail:kingzheng@yeah.net 如要轉發,請注明出處!!

    

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM