/// <summary> /// Calculate a frequency distribution for the provided array of values. /// 1) The minimum and maximum values are found. /// 2) The resulting value range is divided into equal sized sub-ranges (categoryCount). /// 3) The number of values that fall into each category is determined. /// </summary> public static HistogramData BuildHistogramData(double[] valArr, int categoryCount) { // Determine min/max. MathSpanUtils.MinMax(valArr, out double min, out double max); // Note. each bucket's range has interval [low,high), i.e. samples exactly equal to 'high' // will fall into the next highest bucket. Therefore to prevent the maximum sample vAalue falling into the // last bucket by itself, we inflate the range by a small proportion so that the max value falls just below // the max range covered by the distribution. double range = (max - min) * 1.01; // Handle special case where the data series contains a single value. if (0.0 == range) { return(new HistogramData(min, max, 0.0, new int[] { valArr.Length })); } // Loop values and for each one increment the relevant category's frequency count. double incr = range / categoryCount; int[] frequencyArr = new int[categoryCount]; for (int i = 0; i < valArr.Length; i++) { frequencyArr[(int)((valArr[i] - min) / incr)]++; } return(new HistogramData(min, max, incr, frequencyArr)); }
private static void MinMax_Inner(UniformDistributionSampler sampler, int len) { // Alloc arrays and fill with uniform random noise. double[] a = new double[len]; sampler.Sample(a); // Calc results and compare. PointwiseMinMax(a, out double expectedMin, out double expectedMax); MathSpanUtils.MinMax(a, out double actualMin, out double actualMax); Assert.Equal(expectedMin, actualMin, 10); Assert.Equal(expectedMax, actualMax, 10); }
/// <summary> /// Calculate a histogram for the provided span of values. /// 1) The minimum and maximum values are found. /// 2) The resulting value range is divided into equal sized sub-ranges or bins. /// 3) The number of values that fall into each bin is determined. /// </summary> /// <param name="vals">The values to calculate a histogram for.</param> /// <param name="binCount">The number of histogram bins to use.</param> /// <returns>A new instance of <see cref="HistogramData"/>.</returns> public static HistogramData BuildHistogramData(Span <double> vals, int binCount) { // Determine min/max. MathSpanUtils.MinMax(vals, out double min, out double max); // Note. each bin's range has interval [low,high), i.e. samples exactly equal to 'high' will fall // into the next highest bin. Except for the last bin which has interval [low, high]. double range = max - min; // Handle special case where the data series contains a single value. if (range == 0.0) { return(new HistogramData(min, max, 0.0, new int[] { vals.Length })); } // Loop values, and for each one increment the relevant category's frequency count. double incr = range / binCount; int[] frequencyArr = new int[binCount]; for (int i = 0; i < vals.Length; i++) { // Determine which bin the value falls within. int idx = (int)((vals[i] - min) / incr); // Values that equal max, are placed into the last bin. if (idx == vals.Length) { idx--; } frequencyArr[idx]++; } return(new HistogramData(min, max, incr, frequencyArr)); }