using MathNet.Numerics; using MathNet.Numerics.LinearAlgebra.Double; using NPOI.SS.Formula.Functions; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms.DataVisualization.Charting; namespace Hydro.CommonBase { public class CurveFitHelper { public DenseVector coefficients; int degree; double xMax; double xMin; List data; bool isFitted = false; public CurveFitHelper(List data, int degree = 2) { this.degree = degree; this.data = data; double[] xlist = data.Select(p => (double)p.X).ToArray(); if (data.Count>2) { coefficients = Fit.Polynomial(xlist, data.Select(p => (double)p.Y).ToArray(), 2); isFitted = true; } else if(data.Count==2) { //使用两个点的线性拟合 var tuple = Fit.Line(xlist, data.Select(p => (double)p.Y).ToArray()); coefficients= new DenseVector(new double[] { tuple.Item1, tuple.Item2 }); isFitted = true; } else if (data.Count==1) { coefficients = new DenseVector(new double[] { data[0].Y }); isFitted = true; } else { coefficients = new DenseVector(new double[] { 0}); isFitted = true; } var list = xlist.ToList(); xMax = list.Max(); xMin = list.Min(); } public double Evaluate(double x) { if (!isFitted) return double.NaN; double y = 0; for (int i = 0; i < coefficients.Count; i++) { y += (float)(coefficients[i] * Math.Pow(x, i)); } return y; } public List GetFitCurve(int count) { List curve = new List(); for (double x = xMin; x <= xMax && curve.Count> GetConfidenceCurve(int count) { List up_list = new List(); List down_list = new List(); List avg_list = new List(); double X =0; double Y=0; for (double x = xMin; x < xMax; x += (xMax - xMin) / count) { var list = data.FindAll(p => x - (xMax - xMin) / count / 2 <= p.X && p.X < x + (xMax - xMin) / count/2).Select(p => (double)p.Y).ToList(); if (list.Count >= 3) { var Bounds = GetConfidenceRange(list, 95); var x_avg = x; if (Bounds[0] == double.NaN || Bounds[1] == double.NaN) continue; down_list.Add(new PointF((float)x_avg, (float)Bounds[0])); up_list.Add(new PointF((float)x_avg, (float)Bounds[1])); X = x; //平均值 Y = (Bounds[0] + Bounds[1] )/ 2; avg_list.Add(new PointF((float)x_avg, (float)Y)); } else if (list.Count == 2) { var x_avg = x; down_list.Add(new PointF((float)x_avg, (float)list.Min())); up_list.Add(new PointF((float)x_avg, (float)list.Max())); X = x; Y = (list.Min() + list.Max()) / 2; avg_list.Add(new PointF((float)x_avg, (float)Y)); } else if (list.Count == 1) { var x_avg = x; down_list.Add(new PointF((float)x_avg, (float)list[0])); up_list.Add(new PointF((float)x_avg, (float)list[0])); X = x; Y = list[0]; avg_list.Add(new PointF((float)x_avg, (float)Y)); } else if(list.Count == 0) { //使用前一个点的值,X和Y都是前一个点的值 down_list.Add(new PointF((float)X, (float)Y)); up_list.Add(new PointF((float)X, (float)Y)); avg_list.Add(new PointF((float)X, (float)Y)); } } //CurveFitHelper h0 = new CurveFitHelper(down_list); //var curve0 = h0.GetFitCurve(count); //CurveFitHelper h1 = new CurveFitHelper(up_list); //var curve1 = h1.GetFitCurve(count); return new List> { down_list, up_list, avg_list }; } public static double[] GetConfidenceRange(List data, double confidenceLevel = 90, bool mode = true)//true是中位数,置信区间是false { //如果model==true,这计算中位数,比例为confidenceLevel if (mode) { data.Sort(); double lowerBound = 0; double upperBound = 0; //取百分位confidenceLevel/100和1-confidenceLevel/100.0的数 int upperIndex = (int)Math.Round(data.Count * confidenceLevel / 100.0); int lowerIndex = (int)Math.Round(data.Count * (1 - confidenceLevel / 100.0)); if (upperIndex == data.Count) { upperIndex = data.Count - 1; } if (lowerIndex < 0) { lowerIndex = 0; } return new double[] { data[lowerIndex], data[upperIndex] }; } else { // 使用循环计算数据的最小值和最大值 double minValue = double.MaxValue; double maxValue = double.MinValue; foreach (double value in data) { if (value < minValue) { minValue = value; } if (value > maxValue) { maxValue = value; } } // 使用循环计算样本均值 double sum = 0; foreach (double value in data) { sum += value; } double mean = sum / data.Count; // 使用循环计算标准差 double sumOfSquares = 0; foreach (double value in data) { sumOfSquares += Math.Pow(value - mean, 2); } double stdDev = Math.Sqrt(sumOfSquares / (data.Count - 1)); double zValue = 0; double alpha = 1 - confidenceLevel / 100.0; double zValueOneTail = GetZValueOneTail(alpha / 2); double marginOfError = zValueOneTail * stdDev; double lowerBound = mean - marginOfError; double upperBound = mean + marginOfError; return new double[] { lowerBound, upperBound }; } } static double[,] zTable = { {0.0000, 0.0039, 0.0078, 0.0117, 0.0156, 0.0195, 0.0234, 0.0274, 0.0314, 0.0353}, {0.0392, 0.0432, 0.0471, 0.0510, 0.0550, 0.0589, 0.0628, 0.0668, 0.0708, 0.0749}, {0.0789, 0.0830, 0.0871, 0.0912, 0.0953, 0.0994, 0.1035, 0.1076, 0.1117, 0.1158}, {0.1190, 0.1231, 0.1272, 0.1314, 0.1357, 0.1398, 0.1441, 0.1483, 0.1525, 0.1568}, {0.1611, 0.1654, 0.1697, 0.1740, 0.1783, 0.1826, 0.1869, 0.1912, 0.1955, 0.1999}, {0.2042, 0.2085, 0.2129, 0.2172, 0.2216, 0.2260, 0.2304, 0.2348, 0.2392, 0.2436}, {0.2480, 0.2524, 0.2568, 0.2612, 0.2658, 0.2703, 0.2747, 0.2793, 0.2838, 0.2883}, {0.2929, 0.2974, 0.3020, 0.3066, 0.3112, 0.3159, 0.3205, 0.3251, 0.3299, 0.3346}, {0.3393, 0.3441, 0.3487, 0.3535, 0.3583, 0.3632, 0.3679, 0.3727, 0.3776, 0.3823}, {0.3872, 0.3920, 0.3968, 0.4017, 0.4066, 0.4115, 0.4164, 0.4214, 0.4264, 0.4313} }; static double GetZValueOneTail(double alpha) { if (alpha == 0.5) { return 0; } else if (alpha > 0.5) { // Use symmetry property of the normal distribution return -GetZValueOneTail(1 - alpha); } double[] alphaValues = { 0.1, 0.05, 0.025, 0.01, 0.005, 0.001 }; double[] zValues = { 1.28, 1.645, 1.96, 2.33, 2.575, 3.09 }; int n = alphaValues.Length; int i = 0; while (i < n && alpha < alphaValues[i]) { i++; } if (i == 0) { return 0; } else if (i == n) { return zValues[n - 1]; } double x0 = alphaValues[i - 1]; double x1 = alphaValues[i]; double y0 = zValues[i - 1]; double y1 = zValues[i]; double zValue = ((y1 - y0) / (x1 - x0)) * (alpha - x0) + y0; return zValue; } //数据频率分布图的英文怎么说, /// /// 获取数据频率的分布图 /// /// /// /// 以最小值作为过滤的系数 /// public static List GetFrequencyDistribution(List data, out List[] datapoints, int numIntervals = 10,double filterNum=5 ) { List resultPoints = new List(); datapoints= new List[numIntervals]; for(int i=0;i(); } // 设置置信水平 // 设置区间数量 ////在data中过滤和最大的5%的数据 //data = data.Where(d => d <= data.Min() * filterNum).ToList(); // 计算数据的最小值和最大值 double minValue = data.Min(x=>x.ObjFunctionValue); double maxValue = data.Max(x => x.ObjFunctionValue); // 计算区间宽度 double intervalWidth = (maxValue - minValue) / numIntervals; // 初始化频率分布数组 int[] freqDist = new int[numIntervals]; // 计算各个区间的频率 foreach (var xd in data) { var x = xd.ObjFunctionValue; int index = (int)((x - minValue) / intervalWidth); if (index < 0) // 数据小于最小值 { freqDist[0]++; datapoints[0].Add(new DataPoint() {XValue= x,Tag=xd }); } else if (index >= numIntervals) // 数据大于最大值 { freqDist[numIntervals - 1]++; datapoints[numIntervals - 1].Add(new DataPoint() { XValue = x, Tag = xd }); } else // 数据在区间内 { freqDist[index]++; datapoints[index].Add(new DataPoint() { XValue = x, Tag = xd }); } } double[] freqDistPersent =new double[numIntervals]; double sum = freqDist.Sum(); //计算freqDist的频率百分比 for (int i = 0; i < numIntervals; i++) { freqDistPersent[i] = (freqDist[i] / (double)sum ); } //// 计算样本均值和标准差 //double mean = data.Average(); //double stdDev = Math.Sqrt(data.Select(x => (x - mean) * (x - mean)).Sum() / (data.Length - 1)); //double zValue = 0; //double alpha = 1 - confidenceLevel / 100.0; //double zValueOneTail = GetZValueOneTail(alpha / 2); ////zValue = mean + zValueOneTail * stdDev / Math.Sqrt(data.Length); //// 计算置信区间的范围 ////double z = GetZValue(confidenceLevel); //chart1.DataManipulator.Statistics.InverseNormalDistribution(1 - confidenceLevel / 200.0); // 根据置信水平查找标准正态分布的临界值 //double marginOfError = zValueOneTail * stdDev;/// Math.Sqrt(data.Length); //double lowerBound = mean - marginOfError; //double upperBound = mean + marginOfError; for (int i = 0; i < numIntervals; i++) { double xValue = minValue + i * intervalWidth + intervalWidth / 2; double yValue = freqDistPersent[i]; if (isValid(xValue) && isValid(yValue)) resultPoints.Add(new DataPoint(xValue, yValue)); } return resultPoints; } static bool isValid(double value) { if (value == (int)value && value < 0) return false; return !Double.IsNaN(value) && !Double.IsInfinity(value); } } //public static class ConfidenceRangeHelper //{ //} }