Population.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. namespace ScottPlot.Statistics
  6. {
  7. /// <summary>
  8. /// This module holds an array of values and provides popultation statistics (mean, median, standard deviation, etc)
  9. /// </summary>
  10. public class Population
  11. {
  12. public double[] values { get; private set; }
  13. public double[] sortedValues { get; private set; }
  14. public double min { get; private set; }
  15. public double max { get; private set; }
  16. public double median { get; private set; }
  17. public double sum { get; private set; }
  18. public int count { get; private set; }
  19. public double mean { get; private set; }
  20. public double stDev { get; private set; }
  21. public double plus3stDev { get; private set; }
  22. public double minus3stDev { get; private set; }
  23. public double plus2stDev { get; private set; }
  24. public double minus2stDev { get; private set; }
  25. public double stdErr { get; private set; }
  26. public double Q1 { get; private set; }
  27. public double Q3 { get; private set; }
  28. public double IQR { get; private set; }
  29. public double[] lowOutliers { get; private set; }
  30. public double[] highOutliers { get; private set; }
  31. public double maxNonOutlier { get; private set; }
  32. public double minNonOutlier { get; private set; }
  33. public int n { get { return values.Length; } }
  34. public double span { get { return sortedValues.Last() - sortedValues.First(); } }
  35. /// <summary>
  36. /// Generate random values with a normal distribution
  37. /// </summary>
  38. public Population(Random rand, int pointCount, double mean = .5, double stdDev = .5)
  39. {
  40. values = DataGen.RandomNormal(rand, pointCount, mean, stdDev);
  41. Recalculate();
  42. }
  43. /// <summary>
  44. /// Calculate population stats from the given array of values
  45. /// </summary>
  46. public Population(double[] values)
  47. {
  48. if (values is null)
  49. throw new ArgumentException("values cannot be null");
  50. this.values = values;
  51. Recalculate();
  52. }
  53. [Obsolete("This constructor overload is deprecated. Please remove the fullAnalysis argument.")]
  54. public Population(double[] values, bool fullAnalysis = true)
  55. {
  56. if (values is null)
  57. throw new ArgumentException("values cannot be null");
  58. this.values = values;
  59. if (fullAnalysis)
  60. Recalculate();
  61. }
  62. public void Recalculate()
  63. {
  64. count = values.Length;
  65. int QSize = (int)Math.Floor(count / 4.0);
  66. sortedValues = new double[count];
  67. Array.Copy(values, 0, sortedValues, 0, count);
  68. Array.Sort(sortedValues);
  69. min = sortedValues.First();
  70. max = sortedValues.Last();
  71. median = sortedValues[count / 2];
  72. Q1 = sortedValues[QSize];
  73. Q3 = sortedValues[sortedValues.Length - QSize - 1];
  74. IQR = Q3 - Q1;
  75. double lowerBoundary = Q1 - 1.5 * IQR;
  76. double upperBoundary = Q3 + 1.5 * IQR;
  77. int minNonOutlierIndex = 0;
  78. int maxNonOutlierIndex = 0;
  79. for (int i = 0; i < sortedValues.Length; i++)
  80. {
  81. if (sortedValues[i] < lowerBoundary)
  82. {
  83. }
  84. else
  85. {
  86. minNonOutlierIndex = i;
  87. break;
  88. }
  89. }
  90. for (int i = sortedValues.Length - 1; i >= 0; i--)
  91. {
  92. if (sortedValues[i] > upperBoundary)
  93. {
  94. }
  95. else
  96. {
  97. maxNonOutlierIndex = i;
  98. break;
  99. }
  100. }
  101. lowOutliers = new double[minNonOutlierIndex];
  102. highOutliers = new double[sortedValues.Length - maxNonOutlierIndex - 1];
  103. Array.Copy(sortedValues, 0, lowOutliers, 0, lowOutliers.Length);
  104. Array.Copy(sortedValues, maxNonOutlierIndex + 1, highOutliers, 0, highOutliers.Length);
  105. minNonOutlier = sortedValues[minNonOutlierIndex];
  106. maxNonOutlier = sortedValues[maxNonOutlierIndex];
  107. sum = values.Sum();
  108. mean = sum / count;
  109. double sumVariancesSquared = 0;
  110. for (int i = 0; i < values.Length; i++)
  111. {
  112. double pointVariance = Math.Abs(mean - values[i]);
  113. double pointVarianceSquared = Math.Pow(pointVariance, 2);
  114. sumVariancesSquared += pointVarianceSquared;
  115. }
  116. double meanVarianceSquared = sumVariancesSquared / values.Length;
  117. stDev = Math.Sqrt(meanVarianceSquared);
  118. plus2stDev = mean + stDev * 2;
  119. minus2stDev = mean - stDev * 2;
  120. plus3stDev = mean + stDev * 3;
  121. minus3stDev = mean - stDev * 3;
  122. stdErr = stDev / Math.Sqrt(count);
  123. }
  124. public double[] GetDistribution(double[] xs, bool normalize)
  125. {
  126. double[] ys = new double[xs.Length];
  127. for (int i = 0; i < xs.Length; i++)
  128. ys[i] = Math.Exp(-.5 * Math.Pow((xs[i] - mean) / stDev, 2));
  129. if (normalize)
  130. {
  131. double sum = ys.Sum();
  132. for (int i = 0; i < ys.Length; i++)
  133. ys[i] /= sum;
  134. }
  135. return ys;
  136. }
  137. }
  138. }