From c062cb70c751e8b805c01f32711fe4df309015ba Mon Sep 17 00:00:00 2001 From: ddolgushin Date: Fri, 1 Jun 2018 17:41:55 +0500 Subject: [PATCH] + Additional constructor for StandardDeviationClassifier. * Format fix. --- .../JenksFisher/JenksFisherClassifier.cs | 650 +++++++++--------- .../JenksFisher/ValueCountPair.cs | 20 +- .../StandardDeviationClassifier.cs | 56 +- src/Stats/Tests/JenksFisherTest.cs | 38 +- src/Stats/Tests/StandardDeviationTest.cs | 36 +- 5 files changed, 403 insertions(+), 397 deletions(-) diff --git a/src/Stats/Impl/Classification/JenksFisher/JenksFisherClassifier.cs b/src/Stats/Impl/Classification/JenksFisher/JenksFisherClassifier.cs index 184653e..48d7fa3 100644 --- a/src/Stats/Impl/Classification/JenksFisher/JenksFisherClassifier.cs +++ b/src/Stats/Impl/Classification/JenksFisher/JenksFisherClassifier.cs @@ -5,330 +5,330 @@ namespace Stats.Impl.Classification.JenksFisher { - public class JenksFisherClassifier - { - private readonly List _cumulValues; - private readonly int _numValues; - private readonly int _numBreaks; - private readonly int _bufferSize; - private double[] _previousSsm; - private double[] _currentSsm; - private readonly int[] _classBreaks; - private int _classBreaksIndex; - private int _completedRows; - - /// - /// Constructor that initializes main variables used in fisher calculation of natural breaks. - /// - /// ordered list of pairs of values to occurrence counts. - /// number of breaks to find. - private JenksFisherClassifier(ValueCountPair[] vcpc, int k) - { - _cumulValues = new List(); - _numValues = vcpc.Length; - _numBreaks = k; - _bufferSize = _numValues - (k - 1); - _previousSsm = new double[_bufferSize]; - _currentSsm = new double[_bufferSize]; - _classBreaks = new int[_bufferSize * (_numBreaks - 1)]; - _classBreaksIndex = 0; - _completedRows = 0; - - var cwv = 0.0; - var cw = 0; - - for (var i = 0; i != _numValues; ++i) - { - var currPair = vcpc[i]; - Debug.Assert(i == 0 || currPair.Value >= vcpc[i - 1].Value); // PRECONDITION: the value sequence must be strictly increasing - - var w = currPair.Count; - Debug.Assert(w > 0); // PRECONDITION: all weights must be positive - - cw += w; - Debug.Assert(cw >= w); // No overflow? No loss of precision? - - cwv += w * currPair.Value; - _cumulValues.Add(new ValueCountPair(cwv, cw)); - - if (i < _bufferSize) - _previousSsm[i] = cwv * cwv / cw; // prepare sum of squared means for first class. Last (k-1) values are omitted - } - } - - /// - /// Does the internal processing to actually create the breaks. - /// - /// number of breaks. - /// asc ordered input of values and their occurence counts. - /// collection of breaks. - public static double[] Classify(ValueCountPair[] values, int breakCount) - { - var breaksArray = new double[breakCount]; - var m = values.Length; - - Debug.Assert(breakCount <= m); // PRECONDITION - - if (breakCount == 0) - return breaksArray; - - var jf = new JenksFisherClassifier(values, breakCount); - - if (breakCount > 1) - { - // runs the actual calculation - jf.CalcAll(); - - var lastClassBreakIndex = jf.FindMaxBreakIndex(jf._bufferSize - 1, 0, jf._bufferSize); - - while (--breakCount != 0) - { - // assign the break values to the result - breaksArray[breakCount] = values[lastClassBreakIndex + breakCount].Value; - - Debug.Assert(lastClassBreakIndex < jf._bufferSize); - - if (breakCount > 1) - { - jf._classBreaksIndex -= jf._bufferSize; - lastClassBreakIndex = jf._classBreaks[jf._classBreaksIndex + lastClassBreakIndex]; - } - } - - Debug.Assert(jf._classBreaks[jf._classBreaksIndex] == jf._classBreaks[0]); - } - - Debug.Assert(breakCount == 0); - - breaksArray[0] = values[0].Value; // break for the first class is the minimum of the dataset. - - return breaksArray; - } - - /// - /// Main entry point for creation of Jenks-Fisher natural breaks. - /// - /// array of the values, do not need to be sorted. - /// number of breaks to create. - /// collection with breaks. - public static double[] Classify(double[] values, int breakCount) - { - var sortedUniqueValueCounts = GetValueCountPairs(values); - double[] breaksArray; - - if (sortedUniqueValueCounts.Length > breakCount) - breaksArray = Classify(sortedUniqueValueCounts, breakCount); - else - { - var i = 0; - - breaksArray = new double[sortedUniqueValueCounts.Length]; - - foreach (var vcp in sortedUniqueValueCounts) - { - breaksArray[i] = vcp.Value; - - i++; - } - } - - var result = new List(breaksArray.Length); - - result.AddRange(breaksArray); - - return result.ToArray(); - } - - /// - /// Gets sum of weighs for elements with index b..e. - /// - /// index of begin element. - /// index of end element. - /// sum of weights. - private int GetSumOfWeights(int b, int e) - { - Debug.Assert(b != 0); // First element always belongs to class 0, thus queries should never include it. - Debug.Assert(b <= e); - Debug.Assert(e < _numValues); - - var res = _cumulValues[e].Count; - - res -= _cumulValues[b - 1].Count; - - return res; - } - - /// - /// Gets sum of weighed values for elements with index b..e. - /// - /// index of begin element. - /// index of end element. - /// the cumul. sum of the values*weight. - private double GetSumOfWeightedValues(int b, int e) - { - Debug.Assert(b != 0); - Debug.Assert(b <= e); - Debug.Assert(e < _numValues); - - var res = _cumulValues[e].Value; - - res -= _cumulValues[b - 1].Value; - - return res; - } - - /// - /// Gets the Squared Mean for elements within index b..e, multiplied by weight. Note that - /// n*mean^2 = sum^2/n when mean := sum/n. - /// - /// index of begin element. - /// index of end element. - /// the sum of squared mean. - private double GetSsm(int b, int e) - { - var res = GetSumOfWeightedValues(b, e); - - return res * res / GetSumOfWeights(b, e); - } - - /// - /// - /// Finds CB[i+completedRows] given that the result is at least - /// bp+(completedRows-1) and less than ep+(completedRows-1). - /// - /// - /// Complexity: O(ep-bp) <= O(m). - /// - /// - /// startIndex. - /// endindex. - /// - /// The index. - private int FindMaxBreakIndex(int i, int bp, int ep) - { - Debug.Assert(bp < ep); - Debug.Assert(bp <= i); - Debug.Assert(ep <= i + 1); - Debug.Assert(i < _bufferSize); - Debug.Assert(ep <= _bufferSize); - - var minSsm = _previousSsm[bp] + GetSsm(bp + _completedRows, i + _completedRows); - var foundP = bp; - - while (++bp < ep) - { - var currSsm = _previousSsm[bp] + GetSsm(bp + _completedRows, i + _completedRows); - - if (currSsm > minSsm) - { - minSsm = currSsm; - - foundP = bp; - } - } - - _currentSsm[i] = minSsm; - - return foundP; - } - - /// - /// - /// Find CB[i+completedRows] for all i>=bi and i<ei given that the - /// results are at least bp+(completedRows-1) and less than ep+(completedRows-1). - /// - /// - /// Complexity: O(log(ei-bi)*Max((ei-bi),(ep-bp)))<= O(m*log(m)). - /// - /// - private void CalcRange(int bi, int ei, int bp, int ep) - { - Debug.Assert(bi <= ei); - Debug.Assert(ep <= ei); - Debug.Assert(bp <= bi); - - if (bi == ei) - return; - - Debug.Assert(bp < ep); - - var mi = (int)Math.Floor((bi + ei) / 2.0); - var mp = FindMaxBreakIndex(mi, bp, Math.Min(ep, mi + 1)); - - Debug.Assert(bp <= mp); - Debug.Assert(mp < ep); - Debug.Assert(mp <= mi); - - // solve first half of the sub-problems with lower 'half' of possible outcomes - CalcRange(bi, mi, bp, Math.Min(mi, mp + 1)); - - _classBreaks[_classBreaksIndex + mi] = mp; // store result for the middle element. - - // solve second half of the sub-problems with upper 'half' of possible outcomes - CalcRange(mi + 1, ei, mp, ep); - } - - /// - /// Swaps the content of the two lists with each other. - /// - private void SwapArrays() - { - var temp = new double[_previousSsm.Length]; - - Array.Copy(_previousSsm, temp, _previousSsm.Length); - - _previousSsm = new double[_currentSsm.Length]; - - Array.Copy(_currentSsm, _previousSsm, _currentSsm.Length); - - _currentSsm = new double[temp.Length]; - - Array.Copy(temp, _currentSsm, temp.Length); - } - - /// - /// Starting point of calculation of breaks. - /// Complexity: O(m*log(m)*k). - /// - private void CalcAll() - { - if (_numBreaks >= 2) - { - _classBreaksIndex = 0; - for (_completedRows = 1; _completedRows < _numBreaks - 1; ++_completedRows) - { - CalcRange(0, _bufferSize, 0, _bufferSize); // complexity: O(m*log(m)) - - SwapArrays(); - _classBreaksIndex += _bufferSize; - } - } - } - - /// - /// Calculates the occurence count of given values and returns them. - /// - /// - /// Occurences of values. - private static ValueCountPair[] GetValueCountPairs(IReadOnlyCollection values) - { - var result = new List(); - var vcpMap = new Dictionary(); - - foreach (var value in values) - { - if (!vcpMap.ContainsKey(value)) - { - var vcp = new ValueCountPair(value, 1); - - vcpMap.Add(value, vcp); - result.Add(vcp); - } - else - vcpMap[value].Count++; - } - - return result.OrderBy(o => o.Value).ToArray(); + public class JenksFisherClassifier + { + private readonly List _cumulValues; + private readonly int _numValues; + private readonly int _numBreaks; + private readonly int _bufferSize; + private double[] _previousSsm; + private double[] _currentSsm; + private readonly int[] _classBreaks; + private int _classBreaksIndex; + private int _completedRows; + + /// + /// Constructor that initializes main variables used in fisher calculation of natural breaks. + /// + /// ordered list of pairs of values to occurrence counts. + /// number of breaks to find. + private JenksFisherClassifier(ValueCountPair[] vcpc, int k) + { + _cumulValues = new List(); + _numValues = vcpc.Length; + _numBreaks = k; + _bufferSize = _numValues - (k - 1); + _previousSsm = new double[_bufferSize]; + _currentSsm = new double[_bufferSize]; + _classBreaks = new int[_bufferSize * (_numBreaks - 1)]; + _classBreaksIndex = 0; + _completedRows = 0; + + var cwv = 0.0; + var cw = 0; + + for (var i = 0; i != _numValues; ++i) + { + var currPair = vcpc[i]; + Debug.Assert(i == 0 || currPair.Value >= vcpc[i - 1].Value); // PRECONDITION: the value sequence must be strictly increasing + + var w = currPair.Count; + Debug.Assert(w > 0); // PRECONDITION: all weights must be positive + + cw += w; + Debug.Assert(cw >= w); // No overflow? No loss of precision? + + cwv += w * currPair.Value; + _cumulValues.Add(new ValueCountPair(cwv, cw)); + + if (i < _bufferSize) + _previousSsm[i] = cwv * cwv / cw; // prepare sum of squared means for first class. Last (k-1) values are omitted + } } - } + + /// + /// Does the internal processing to actually create the breaks. + /// + /// number of breaks. + /// asc ordered input of values and their occurence counts. + /// collection of breaks. + public static double[] Classify(ValueCountPair[] values, int breakCount) + { + var breaksArray = new double[breakCount]; + var m = values.Length; + + Debug.Assert(breakCount <= m); // PRECONDITION + + if (breakCount == 0) + return breaksArray; + + var jf = new JenksFisherClassifier(values, breakCount); + + if (breakCount > 1) + { + // runs the actual calculation + jf.CalcAll(); + + var lastClassBreakIndex = jf.FindMaxBreakIndex(jf._bufferSize - 1, 0, jf._bufferSize); + + while (--breakCount != 0) + { + // assign the break values to the result + breaksArray[breakCount] = values[lastClassBreakIndex + breakCount].Value; + + Debug.Assert(lastClassBreakIndex < jf._bufferSize); + + if (breakCount > 1) + { + jf._classBreaksIndex -= jf._bufferSize; + lastClassBreakIndex = jf._classBreaks[jf._classBreaksIndex + lastClassBreakIndex]; + } + } + + Debug.Assert(jf._classBreaks[jf._classBreaksIndex] == jf._classBreaks[0]); + } + + Debug.Assert(breakCount == 0); + + breaksArray[0] = values[0].Value; // break for the first class is the minimum of the dataset. + + return breaksArray; + } + + /// + /// Main entry point for creation of Jenks-Fisher natural breaks. + /// + /// array of the values, do not need to be sorted. + /// number of breaks to create. + /// collection with breaks. + public static double[] Classify(double[] values, int breakCount) + { + var sortedUniqueValueCounts = GetValueCountPairs(values); + double[] breaksArray; + + if (sortedUniqueValueCounts.Length > breakCount) + breaksArray = Classify(sortedUniqueValueCounts, breakCount); + else + { + var i = 0; + + breaksArray = new double[sortedUniqueValueCounts.Length]; + + foreach (var vcp in sortedUniqueValueCounts) + { + breaksArray[i] = vcp.Value; + + i++; + } + } + + var result = new List(breaksArray.Length); + + result.AddRange(breaksArray); + + return result.ToArray(); + } + + /// + /// Gets sum of weighs for elements with index b..e. + /// + /// index of begin element. + /// index of end element. + /// sum of weights. + private int GetSumOfWeights(int b, int e) + { + Debug.Assert(b != 0); // First element always belongs to class 0, thus queries should never include it. + Debug.Assert(b <= e); + Debug.Assert(e < _numValues); + + var res = _cumulValues[e].Count; + + res -= _cumulValues[b - 1].Count; + + return res; + } + + /// + /// Gets sum of weighed values for elements with index b..e. + /// + /// index of begin element. + /// index of end element. + /// the cumul. sum of the values*weight. + private double GetSumOfWeightedValues(int b, int e) + { + Debug.Assert(b != 0); + Debug.Assert(b <= e); + Debug.Assert(e < _numValues); + + var res = _cumulValues[e].Value; + + res -= _cumulValues[b - 1].Value; + + return res; + } + + /// + /// Gets the Squared Mean for elements within index b..e, multiplied by weight. Note that + /// n*mean^2 = sum^2/n when mean := sum/n. + /// + /// index of begin element. + /// index of end element. + /// the sum of squared mean. + private double GetSsm(int b, int e) + { + var res = GetSumOfWeightedValues(b, e); + + return res * res / GetSumOfWeights(b, e); + } + + /// + /// + /// Finds CB[i+completedRows] given that the result is at least + /// bp+(completedRows-1) and less than ep+(completedRows-1). + /// + /// + /// Complexity: O(ep-bp) <= O(m). + /// + /// + /// startIndex. + /// endindex. + /// + /// The index. + private int FindMaxBreakIndex(int i, int bp, int ep) + { + Debug.Assert(bp < ep); + Debug.Assert(bp <= i); + Debug.Assert(ep <= i + 1); + Debug.Assert(i < _bufferSize); + Debug.Assert(ep <= _bufferSize); + + var minSsm = _previousSsm[bp] + GetSsm(bp + _completedRows, i + _completedRows); + var foundP = bp; + + while (++bp < ep) + { + var currSsm = _previousSsm[bp] + GetSsm(bp + _completedRows, i + _completedRows); + + if (currSsm > minSsm) + { + minSsm = currSsm; + + foundP = bp; + } + } + + _currentSsm[i] = minSsm; + + return foundP; + } + + /// + /// + /// Find CB[i+completedRows] for all i>=bi and i<ei given that the + /// results are at least bp+(completedRows-1) and less than ep+(completedRows-1). + /// + /// + /// Complexity: O(log(ei-bi)*Max((ei-bi),(ep-bp)))<= O(m*log(m)). + /// + /// + private void CalcRange(int bi, int ei, int bp, int ep) + { + Debug.Assert(bi <= ei); + Debug.Assert(ep <= ei); + Debug.Assert(bp <= bi); + + if (bi == ei) + return; + + Debug.Assert(bp < ep); + + var mi = (int)Math.Floor((bi + ei) / 2.0); + var mp = FindMaxBreakIndex(mi, bp, Math.Min(ep, mi + 1)); + + Debug.Assert(bp <= mp); + Debug.Assert(mp < ep); + Debug.Assert(mp <= mi); + + // solve first half of the sub-problems with lower 'half' of possible outcomes + CalcRange(bi, mi, bp, Math.Min(mi, mp + 1)); + + _classBreaks[_classBreaksIndex + mi] = mp; // store result for the middle element. + + // solve second half of the sub-problems with upper 'half' of possible outcomes + CalcRange(mi + 1, ei, mp, ep); + } + + /// + /// Swaps the content of the two lists with each other. + /// + private void SwapArrays() + { + var temp = new double[_previousSsm.Length]; + + Array.Copy(_previousSsm, temp, _previousSsm.Length); + + _previousSsm = new double[_currentSsm.Length]; + + Array.Copy(_currentSsm, _previousSsm, _currentSsm.Length); + + _currentSsm = new double[temp.Length]; + + Array.Copy(temp, _currentSsm, temp.Length); + } + + /// + /// Starting point of calculation of breaks. + /// Complexity: O(m*log(m)*k). + /// + private void CalcAll() + { + if (_numBreaks >= 2) + { + _classBreaksIndex = 0; + for (_completedRows = 1; _completedRows < _numBreaks - 1; ++_completedRows) + { + CalcRange(0, _bufferSize, 0, _bufferSize); // complexity: O(m*log(m)) + + SwapArrays(); + _classBreaksIndex += _bufferSize; + } + } + } + + /// + /// Calculates the occurence count of given values and returns them. + /// + /// + /// Occurences of values. + private static ValueCountPair[] GetValueCountPairs(IReadOnlyCollection values) + { + var result = new List(); + var vcpMap = new Dictionary(); + + foreach (var value in values) + { + if (!vcpMap.ContainsKey(value)) + { + var vcp = new ValueCountPair(value, 1); + + vcpMap.Add(value, vcp); + result.Add(vcp); + } + else + vcpMap[value].Count++; + } + + return result.OrderBy(o => o.Value).ToArray(); + } + } } diff --git a/src/Stats/Impl/Classification/JenksFisher/ValueCountPair.cs b/src/Stats/Impl/Classification/JenksFisher/ValueCountPair.cs index 767979a..7f138e9 100644 --- a/src/Stats/Impl/Classification/JenksFisher/ValueCountPair.cs +++ b/src/Stats/Impl/Classification/JenksFisher/ValueCountPair.cs @@ -1,15 +1,15 @@ namespace Stats.Impl.Classification.JenksFisher { - public class ValueCountPair - { - public ValueCountPair(double value, int count) - { - Value = value; - Count = count; - } + public class ValueCountPair + { + public ValueCountPair(double value, int count) + { + Value = value; + Count = count; + } - public double Value { get; set; } + public double Value { get; set; } - public int Count { get; set; } - } + public int Count { get; set; } + } } diff --git a/src/Stats/Impl/Classification/StandardDeviation/StandardDeviationClassifier.cs b/src/Stats/Impl/Classification/StandardDeviation/StandardDeviationClassifier.cs index d5d9aa8..e0f3c48 100644 --- a/src/Stats/Impl/Classification/StandardDeviation/StandardDeviationClassifier.cs +++ b/src/Stats/Impl/Classification/StandardDeviation/StandardDeviationClassifier.cs @@ -3,33 +3,39 @@ namespace Stats.Impl.Classification.StandardDeviation { - public class StandardDeviationClassifier - { - public static double[] Classify(double[] values) - { - var res = new double[8]; - var orderedValues = values.OrderBy(o => o).ToArray(); - var stdDeviation = GetStandardDeviation(orderedValues); - var mean = orderedValues.Average(); + public class StandardDeviationClassifier + { + public static double[] Classify(double[] values) + { + return Classify(values, out _, out _); + } - res[0] = double.MinValue; - res[1] = mean - 3 * stdDeviation; - res[2] = mean - 2 * stdDeviation; - res[3] = mean - stdDeviation; - res[4] = mean + stdDeviation; - res[5] = mean + 2 * stdDeviation; - res[6] = mean + 3 * stdDeviation; - res[7] = double.MaxValue; + public static double[] Classify(double[] values, out double mean, out double stdDeviation) + { + var res = new double[8]; + var orderedValues = values.OrderBy(o => o).ToArray(); - return res; - } + stdDeviation = GetStandardDeviation(orderedValues); + mean = orderedValues.Average(); - internal static double GetStandardDeviation(double[] values) - { - var mean = values.Average(); - var variance = values.Select(o => Math.Pow(o - mean, 2)).Sum() / values.Length; + res[0] = double.MinValue; + res[1] = mean - 3 * stdDeviation; + res[2] = mean - 2 * stdDeviation; + res[3] = mean - stdDeviation; + res[4] = mean + stdDeviation; + res[5] = mean + 2 * stdDeviation; + res[6] = mean + 3 * stdDeviation; + res[7] = double.MaxValue; - return Math.Sqrt(variance); - } - } + return res; + } + + internal static double GetStandardDeviation(double[] values) + { + var mean = values.Average(); + var variance = values.Select(o => Math.Pow(o - mean, 2)).Sum() / values.Length; + + return Math.Sqrt(variance); + } + } } diff --git a/src/Stats/Tests/JenksFisherTest.cs b/src/Stats/Tests/JenksFisherTest.cs index ee2f612..121aafc 100644 --- a/src/Stats/Tests/JenksFisherTest.cs +++ b/src/Stats/Tests/JenksFisherTest.cs @@ -3,26 +3,26 @@ namespace Stats.Tests { - public class JenksFisherTest - { - [Fact] - public void BreaksArrayIsCorrect_1_Test() - { - var values = new [] { 0.0, 0.4138551597318488, 0.8303053173655336, 1.2565109043406852, 1.6886744171510624, 2.1406670053984556, 2.5916380635166125, 3.0602181476985986, 3.530142278860191, 3.980113866940125, 4.4444599263298405, 4.94381368531848, 5.521662038230455, 6.169176493757194, 6.738258965168605, 7.319391438686014, 7.932223894860435, 8.61476247800988, 9.353267587309293, 10.150097580516201, 11.069662632065183, 11.908240183389738, 12.706557961047151, 13.645913772393229, 14.357937463403129, 15.362870037920171, 16.391252937979583, 17.604667761713984, 18.600192490837937, 19.8133530796433, 20.92638115833033, 22.030037235901958, 23.388567729401547, 24.688972510315363, 26.137950829123785, 27.309226078343155, 28.563645069036212, 30.084421598561406, 31.105074108454748, 32.74802642845182, 33.68170026667428, 35.091337260188766, 36.78656550195054, 39.42209378453451, 40.514622125606635, 41.58444692822636, 43.4396023274846, 45.6346551957123, 47.77350858873818, 49.45083508855724, 51.22280695104019, 53.08759237876448, 54.55678135070922, 58.43482830215892, 60.47755830320076, 62.190346912906804, 64.51566019627748, 66.61000296187834, 69.42423114239936, 71.95831140342538, 73.29035444007805, 75.45359118001146, 78.25928901805739, 80.13937153292244, 85.86894726924331, 88.97307664255395, 92.2722182072519, 96.81774605038419, 99.01692675006565, 102.12069172725647, 104.84483683667891, 110.6920535027623, 113.81326765613655, 120.84317833337806, 124.4818113651608, 129.88821288309472, 133.09639656864755, 142.6327762753434, 145.64427208215466, 149.046520040376, 153.72565044093184, 160.6373088051857, 171.30242740184136, 187.803602064211, 195.10721769647517, 198.33594810697747, 207.13717780459308, 229.28030802584811, 254.78401165637874, 273.62341829207816, 281.98515874623854, 293.1571764760844, 415.12524438185454, 449.48087901921804, 470.5097535400657, 479.6448325080552, 572.7167641131507, 607.9191863053611, 610.2327211640173, 621.6628009389376, 0.0, 1.10361375928493, 2.476504340582577, 3.9313403965985327, 5.455797408047881, 6.910676716811881, 8.142888669983712, 9.444332198149613, 10.94816261058246, 12.725439909511508, 14.601759579873042, 16.330290866178707, 18.18672078684219, 20.22663701433632, 22.030037235943624, 23.843067188665756, 26.106355137563632, 28.133654713359434, 30.240730464966344, 32.07152103613903, 33.89730310010673, 35.77709770966313, 37.777324045909424, 39.630095301539626, 41.72983682644778, 43.81546524985761, 46.61311560401082, 48.773191795474936, 51.39923831317205, 53.707162803586584, 56.00485483018517, 58.54020922859034, 61.57426023293155, 63.69156822689917, 66.44755142142738, 69.58304611126833, 72.74236599421108, 75.63657647871206, 79.82859556850039, 83.19651320004714, 86.79222107634918, 89.92749067115783, 94.41180227714051, 98.19899604644229, 101.56594923810309, 105.93645383274753, 110.40951078990082, 116.93181471645232, 122.5782489402401, 126.59645638446794, 131.98852265550667, 137.63785624086913, 141.17381855270818, 145.22793701432371, 151.34652941589596, 155.7340460365189, 161.51478251473807, 166.8000591885745, 177.1814023099512, 184.8737274083608, 188.95004781286818, 195.17483828375438, 211.29379094272056, 219.16865484028062, 226.6757044053862, 235.86896388723443, 247.51611375344868, 256.4858086634747, 263.0300550391084, 268.3849470146043, 276.5101265473909, 287.421469006056, 297.3076174948901, 305.7921230196989, 318.06274664521624, 327.0377279064577, 353.4020793727573, 359.68661527526723, 367.63870018757905, 393.0675220780585, 418.42508466714645, 437.6936919416369, 456.47274644865615, 512.8891533886153, 530.8899140390158, 565.1037504333227, 585.8477258053761, 608.4574831690682, 664.6271146809149, 713.5575854007886, 727.6602706479734, 748.9914482132681, 775.1561318407973, 793.9935563617684, 846.0385011649819, 876.9871372863854, 886.0095054759232, 993.4111125488206, 1171.8965362343667, 1226.3372190293937, 0.0, 1.105689347611934, 2.3799486695605108, 3.689746428586369, 4.8300717399266375, 6.022232257111756, 7.189653356244446, 8.598149486180105, 9.868140258053844, 11.300143673479143, 13.25461382486289, 15.076605548387628, 16.730677163493116, 18.692058986983014, 20.406874297144135, 22.29615228210549, 24.214759656347088, 26.161437377422136, 28.256121593470574, 30.618883618352697, 32.99134963813075, 35.59381447789526, 38.4063529272879, 41.65874219851036, 44.36876070008579, 47.62134941693816, 50.448919147919504, 53.543540428966836, 57.743710516357694, 61.245309662728936, 64.66243494026449, 67.82019144879435, 70.7932295506916, 74.06691753094609, 77.85876162879225, 82.28484970861979, 84.65677512651746, 88.99094593750965, 93.20254392105501, 100.14498584899442, 103.83360186852495, 110.02685772352822, 117.41335907473368, 122.5608489264608, 133.11588884969595, 139.25564525729038, 146.49587456993237, 150.65728107090143, 156.1720454993405, 163.67203481350808, 168.54070935837993, 173.6417351191969, 177.35766351428876, 183.10090103132626, 192.37574482694046, 198.88436716143036, 208.64363566577077, 212.2425738435236, 220.93245762867593, 226.66048182544313, 229.90792661376298, 240.23191799060078, 246.12026100763256, 255.49050689379217, 261.0915908927656, 267.74509310972456, 278.7951544766378, 289.4670866083692, 297.14112857261443, 308.85127699650843, 315.4900668292883, 325.1655255196537, 337.0231127887081, 346.8957423562269, 354.19625938950134, 379.62722203102885, 386.24136792639985, 403.7368825485725, 413.06190755672554, 426.2698777347118, 442.2691948736135, 491.35346619839254, 507.3313732841482, 548.6246330239783, 595.5750586625157, 614.96641481912, 637.6212408612957, 680.1195443750318, 723.32098288124, 759.3576115397818, 797.053774509455, 804.1199178700465, 1213.4430220392671, 1221.5267166345889, 1230.9978814075932, 1343.6867410306816, 1366.0402208321018, 1608.4782133914912, 1662.8079783673027, 1700.4098740909435, 0.0, 1.125909524653281, 2.5570833699036317, 4.007828017257608, 5.34377001821906, 6.6341369192600235, 8.003372168812168, 9.206271333145866, 10.490599758786079, 12.224751965682515, 13.758978176273864, 15.011982029412945, 16.33746424862115, 18.063197889178046, 19.8527282113889, 21.704303602091084, 23.538241631041224, 25.226063068497513, 27.616553733476156, 30.267554434971967, 32.83682200208433, 34.897143015149915, 37.56154313362505, 39.51667009176536, 41.38890877644773, 44.180683291310565, 46.76478859393878, 49.80479223698172, 53.420764621575195, 56.80164366196311, 60.30971504627013, 63.566306418285365, 66.3017562227123, 69.0532754480599, 72.20347995643066, 76.99860087379552, 80.22980467782224, 84.47816638409557, 87.82985921080727, 92.22580313259944, 97.99749015446204, 103.32243743988565, 108.51214125494351, 116.52738644209508, 121.13900763633099, 125.53545476357918, 132.75975509951593, 137.99662085966133, 142.75501699565194, 148.5196075543186, 153.70149696146652, 157.942586656512, 164.158861383067, 170.72965299031327, 177.40138620672369, 182.74824460207603, 189.40321316307654, 196.20581892259787, 200.5314036626666, 206.7369234547661, 220.78726988537423, 228.50823318707356, 235.3856258464819, 240.9257256331181, 248.47506255295346, 255.2104958234474, 261.6603637091074, 273.5352935340383, 278.321767756141, 289.91854678410675, 294.9169857177481, 305.4268908182343, 313.27973328070084, 322.30696023736226, 344.31459112324046, 358.8840094117526, 379.4005238331545, 386.1966112364132, 395.23347570241157, 404.2816992011444, 452.66937958816413, 469.32261971859566, 502.473850103632, 539.1687435828383, 545.8661995613214, 569.0349415561858, 623.8364295187006, 655.6791441645117, 678.3521685212124, 712.6316695221836, 747.0346237089271, 1064.4237035432168, 1080.6893745419004, 1112.6878090009438, 1174.8439747306104, 1206.7974673194676, 1419.6104428920466, 1438.873045760802, 1464.485721451147, 1479.8072839229048, 0.0, 0.9123349469315073, 2.0337266038058726, 3.224306462449907, 4.509137573552907, 5.920856107014794, 7.218506997837273, 8.392368420516362, 9.5522732806563, 10.949670818398983, 12.377938592115283, 13.90019990496801, 15.474284052307116, 17.114489627842538, 18.680853004092754, 20.210449679088587, 21.939596089699545, 23.943975943323302, 25.557936364892324, 27.54870325457253, 29.053357145115328, 31.1753036287 }; - var breaks = JenksFisherClassifier.Classify(values, 15); - var expectedValues = new [] { 0.0, 34.897143015149915, 77.85876162879225, 129.88821288309472, 187.803602064211, 254.78401165637874, 337.0231127887081, 426.2698777347118, 530.8899140390158, 655.6791441645117, 775.1561318407973, 993.4111125488206, 1171.8965362343667, 1343.6867410306816, 1608.4782133914912 }; + public class JenksFisherTest + { + [Fact] + public void BreaksArrayIsCorrect_1_Test() + { + var values = new[] { 0.0, 0.4138551597318488, 0.8303053173655336, 1.2565109043406852, 1.6886744171510624, 2.1406670053984556, 2.5916380635166125, 3.0602181476985986, 3.530142278860191, 3.980113866940125, 4.4444599263298405, 4.94381368531848, 5.521662038230455, 6.169176493757194, 6.738258965168605, 7.319391438686014, 7.932223894860435, 8.61476247800988, 9.353267587309293, 10.150097580516201, 11.069662632065183, 11.908240183389738, 12.706557961047151, 13.645913772393229, 14.357937463403129, 15.362870037920171, 16.391252937979583, 17.604667761713984, 18.600192490837937, 19.8133530796433, 20.92638115833033, 22.030037235901958, 23.388567729401547, 24.688972510315363, 26.137950829123785, 27.309226078343155, 28.563645069036212, 30.084421598561406, 31.105074108454748, 32.74802642845182, 33.68170026667428, 35.091337260188766, 36.78656550195054, 39.42209378453451, 40.514622125606635, 41.58444692822636, 43.4396023274846, 45.6346551957123, 47.77350858873818, 49.45083508855724, 51.22280695104019, 53.08759237876448, 54.55678135070922, 58.43482830215892, 60.47755830320076, 62.190346912906804, 64.51566019627748, 66.61000296187834, 69.42423114239936, 71.95831140342538, 73.29035444007805, 75.45359118001146, 78.25928901805739, 80.13937153292244, 85.86894726924331, 88.97307664255395, 92.2722182072519, 96.81774605038419, 99.01692675006565, 102.12069172725647, 104.84483683667891, 110.6920535027623, 113.81326765613655, 120.84317833337806, 124.4818113651608, 129.88821288309472, 133.09639656864755, 142.6327762753434, 145.64427208215466, 149.046520040376, 153.72565044093184, 160.6373088051857, 171.30242740184136, 187.803602064211, 195.10721769647517, 198.33594810697747, 207.13717780459308, 229.28030802584811, 254.78401165637874, 273.62341829207816, 281.98515874623854, 293.1571764760844, 415.12524438185454, 449.48087901921804, 470.5097535400657, 479.6448325080552, 572.7167641131507, 607.9191863053611, 610.2327211640173, 621.6628009389376, 0.0, 1.10361375928493, 2.476504340582577, 3.9313403965985327, 5.455797408047881, 6.910676716811881, 8.142888669983712, 9.444332198149613, 10.94816261058246, 12.725439909511508, 14.601759579873042, 16.330290866178707, 18.18672078684219, 20.22663701433632, 22.030037235943624, 23.843067188665756, 26.106355137563632, 28.133654713359434, 30.240730464966344, 32.07152103613903, 33.89730310010673, 35.77709770966313, 37.777324045909424, 39.630095301539626, 41.72983682644778, 43.81546524985761, 46.61311560401082, 48.773191795474936, 51.39923831317205, 53.707162803586584, 56.00485483018517, 58.54020922859034, 61.57426023293155, 63.69156822689917, 66.44755142142738, 69.58304611126833, 72.74236599421108, 75.63657647871206, 79.82859556850039, 83.19651320004714, 86.79222107634918, 89.92749067115783, 94.41180227714051, 98.19899604644229, 101.56594923810309, 105.93645383274753, 110.40951078990082, 116.93181471645232, 122.5782489402401, 126.59645638446794, 131.98852265550667, 137.63785624086913, 141.17381855270818, 145.22793701432371, 151.34652941589596, 155.7340460365189, 161.51478251473807, 166.8000591885745, 177.1814023099512, 184.8737274083608, 188.95004781286818, 195.17483828375438, 211.29379094272056, 219.16865484028062, 226.6757044053862, 235.86896388723443, 247.51611375344868, 256.4858086634747, 263.0300550391084, 268.3849470146043, 276.5101265473909, 287.421469006056, 297.3076174948901, 305.7921230196989, 318.06274664521624, 327.0377279064577, 353.4020793727573, 359.68661527526723, 367.63870018757905, 393.0675220780585, 418.42508466714645, 437.6936919416369, 456.47274644865615, 512.8891533886153, 530.8899140390158, 565.1037504333227, 585.8477258053761, 608.4574831690682, 664.6271146809149, 713.5575854007886, 727.6602706479734, 748.9914482132681, 775.1561318407973, 793.9935563617684, 846.0385011649819, 876.9871372863854, 886.0095054759232, 993.4111125488206, 1171.8965362343667, 1226.3372190293937, 0.0, 1.105689347611934, 2.3799486695605108, 3.689746428586369, 4.8300717399266375, 6.022232257111756, 7.189653356244446, 8.598149486180105, 9.868140258053844, 11.300143673479143, 13.25461382486289, 15.076605548387628, 16.730677163493116, 18.692058986983014, 20.406874297144135, 22.29615228210549, 24.214759656347088, 26.161437377422136, 28.256121593470574, 30.618883618352697, 32.99134963813075, 35.59381447789526, 38.4063529272879, 41.65874219851036, 44.36876070008579, 47.62134941693816, 50.448919147919504, 53.543540428966836, 57.743710516357694, 61.245309662728936, 64.66243494026449, 67.82019144879435, 70.7932295506916, 74.06691753094609, 77.85876162879225, 82.28484970861979, 84.65677512651746, 88.99094593750965, 93.20254392105501, 100.14498584899442, 103.83360186852495, 110.02685772352822, 117.41335907473368, 122.5608489264608, 133.11588884969595, 139.25564525729038, 146.49587456993237, 150.65728107090143, 156.1720454993405, 163.67203481350808, 168.54070935837993, 173.6417351191969, 177.35766351428876, 183.10090103132626, 192.37574482694046, 198.88436716143036, 208.64363566577077, 212.2425738435236, 220.93245762867593, 226.66048182544313, 229.90792661376298, 240.23191799060078, 246.12026100763256, 255.49050689379217, 261.0915908927656, 267.74509310972456, 278.7951544766378, 289.4670866083692, 297.14112857261443, 308.85127699650843, 315.4900668292883, 325.1655255196537, 337.0231127887081, 346.8957423562269, 354.19625938950134, 379.62722203102885, 386.24136792639985, 403.7368825485725, 413.06190755672554, 426.2698777347118, 442.2691948736135, 491.35346619839254, 507.3313732841482, 548.6246330239783, 595.5750586625157, 614.96641481912, 637.6212408612957, 680.1195443750318, 723.32098288124, 759.3576115397818, 797.053774509455, 804.1199178700465, 1213.4430220392671, 1221.5267166345889, 1230.9978814075932, 1343.6867410306816, 1366.0402208321018, 1608.4782133914912, 1662.8079783673027, 1700.4098740909435, 0.0, 1.125909524653281, 2.5570833699036317, 4.007828017257608, 5.34377001821906, 6.6341369192600235, 8.003372168812168, 9.206271333145866, 10.490599758786079, 12.224751965682515, 13.758978176273864, 15.011982029412945, 16.33746424862115, 18.063197889178046, 19.8527282113889, 21.704303602091084, 23.538241631041224, 25.226063068497513, 27.616553733476156, 30.267554434971967, 32.83682200208433, 34.897143015149915, 37.56154313362505, 39.51667009176536, 41.38890877644773, 44.180683291310565, 46.76478859393878, 49.80479223698172, 53.420764621575195, 56.80164366196311, 60.30971504627013, 63.566306418285365, 66.3017562227123, 69.0532754480599, 72.20347995643066, 76.99860087379552, 80.22980467782224, 84.47816638409557, 87.82985921080727, 92.22580313259944, 97.99749015446204, 103.32243743988565, 108.51214125494351, 116.52738644209508, 121.13900763633099, 125.53545476357918, 132.75975509951593, 137.99662085966133, 142.75501699565194, 148.5196075543186, 153.70149696146652, 157.942586656512, 164.158861383067, 170.72965299031327, 177.40138620672369, 182.74824460207603, 189.40321316307654, 196.20581892259787, 200.5314036626666, 206.7369234547661, 220.78726988537423, 228.50823318707356, 235.3856258464819, 240.9257256331181, 248.47506255295346, 255.2104958234474, 261.6603637091074, 273.5352935340383, 278.321767756141, 289.91854678410675, 294.9169857177481, 305.4268908182343, 313.27973328070084, 322.30696023736226, 344.31459112324046, 358.8840094117526, 379.4005238331545, 386.1966112364132, 395.23347570241157, 404.2816992011444, 452.66937958816413, 469.32261971859566, 502.473850103632, 539.1687435828383, 545.8661995613214, 569.0349415561858, 623.8364295187006, 655.6791441645117, 678.3521685212124, 712.6316695221836, 747.0346237089271, 1064.4237035432168, 1080.6893745419004, 1112.6878090009438, 1174.8439747306104, 1206.7974673194676, 1419.6104428920466, 1438.873045760802, 1464.485721451147, 1479.8072839229048, 0.0, 0.9123349469315073, 2.0337266038058726, 3.224306462449907, 4.509137573552907, 5.920856107014794, 7.218506997837273, 8.392368420516362, 9.5522732806563, 10.949670818398983, 12.377938592115283, 13.90019990496801, 15.474284052307116, 17.114489627842538, 18.680853004092754, 20.210449679088587, 21.939596089699545, 23.943975943323302, 25.557936364892324, 27.54870325457253, 29.053357145115328, 31.1753036287 }; + var breaks = JenksFisherClassifier.Classify(values, 15); + var expectedValues = new[] { 0.0, 34.897143015149915, 77.85876162879225, 129.88821288309472, 187.803602064211, 254.78401165637874, 337.0231127887081, 426.2698777347118, 530.8899140390158, 655.6791441645117, 775.1561318407973, 993.4111125488206, 1171.8965362343667, 1343.6867410306816, 1608.4782133914912 }; - Assert.Equal(breaks, expectedValues); - } + Assert.Equal(breaks, expectedValues); + } - [Fact] - public void BreaksArrayIsCorrect_2_Test() - { - var values = new [] { 0.0, 0.0, 10.0, 10.0, 10.0, 10.0, 100.0, 100.0, 1002.0, 10040.0, 1009.0, 101.0, 101.0, 1010.0, 1011.0, 1012.0, 1015.0, 1017.0, 1018.0, 102.0, 102.0, 1020.0 }; - var breaks = JenksFisherClassifier.Classify(values, 10); - var expectedValues = new [] { 0.0, 10.0, 100.0, 1002.0, 1009.0, 1011.0, 1015.0, 1017.0, 1020.0, 10040.0 }; + [Fact] + public void BreaksArrayIsCorrect_2_Test() + { + var values = new[] { 0.0, 0.0, 10.0, 10.0, 10.0, 10.0, 100.0, 100.0, 1002.0, 10040.0, 1009.0, 101.0, 101.0, 1010.0, 1011.0, 1012.0, 1015.0, 1017.0, 1018.0, 102.0, 102.0, 1020.0 }; + var breaks = JenksFisherClassifier.Classify(values, 10); + var expectedValues = new[] { 0.0, 10.0, 100.0, 1002.0, 1009.0, 1011.0, 1015.0, 1017.0, 1020.0, 10040.0 }; - Assert.Equal(breaks, expectedValues); - } - } + Assert.Equal(breaks, expectedValues); + } + } } diff --git a/src/Stats/Tests/StandardDeviationTest.cs b/src/Stats/Tests/StandardDeviationTest.cs index 089f4cf..e26ed67 100644 --- a/src/Stats/Tests/StandardDeviationTest.cs +++ b/src/Stats/Tests/StandardDeviationTest.cs @@ -4,25 +4,25 @@ namespace Stats.Tests { - public class StandardDeviationTest - { - [Fact] - public void StandardDeviationCalculationResultIsCorrectTest() - { - var values = new [] { 14.0, 18, 12, 15, 11, 19, 13, 22 }; - var res = StandardDeviationClassifier.GetStandardDeviation(values); + public class StandardDeviationTest + { + [Fact] + public void StandardDeviationCalculationResultIsCorrectTest() + { + var values = new[] { 14.0, 18, 12, 15, 11, 19, 13, 22 }; + var res = StandardDeviationClassifier.GetStandardDeviation(values); - Assert.Equal(3.57, Math.Round(res, 2)); - } + Assert.Equal(3.57, Math.Round(res, 2)); + } - [Fact] - public void BreaksArrayIsCorrectTest() - { - var values = new [] { 79.0, 78, 77, 75, 75, 74, 74, 74, 74, 70 }; - var breaks = StandardDeviationClassifier.Classify(values); - var expectedValues = new [] { double.MinValue, 67.7750432527246224, 70.1833621684830816, 72.5916810842415408, 77.4083189157584592, 79.8166378315169184, 82.2249567472753776, double.MaxValue }; + [Fact] + public void BreaksArrayIsCorrectTest() + { + var values = new[] { 79.0, 78, 77, 75, 75, 74, 74, 74, 74, 70 }; + var breaks = StandardDeviationClassifier.Classify(values); + var expectedValues = new[] { double.MinValue, 67.7750432527246224, 70.1833621684830816, 72.5916810842415408, 77.4083189157584592, 79.8166378315169184, 82.2249567472753776, double.MaxValue }; - Assert.Equal(breaks, expectedValues); - } - } + Assert.Equal(breaks, expectedValues); + } + } }