Browse Source

Statistics: add Skewness, PopulationSkewness, Kurtosis and PopulationKurtosis #210

pull/222/head
Christoph Ruegg 12 years ago
parent
commit
b0ecf6c947
  1. 2
      src/Numerics/Statistics/RunningStatistics.cs
  2. 128
      src/Numerics/Statistics/Statistics.cs
  3. 62
      src/UnitTests/StatisticsTests/RunningStatisticsTests.cs

2
src/Numerics/Statistics/RunningStatistics.cs

@ -225,7 +225,7 @@ namespace MathNet.Numerics.Statistics
double m1 = (a._n*a._m1 + b._n*b._m1)/n;
double m2 = a._m2 + b._m2 + d2*a._n*b._n/n;
double m3 = a._m3 + b._m3 + d3*a._n*b._n*(a._n - b._n)/(n*n)
+ 3*d3*(a._n*b._m2 - b._n*a._m2)/n;
+ 3*d*(a._n*b._m2 - b._n*a._m2)/n;
double m4 = a._m4 + b._m4 + d4*a._n*b._n*(a._n*a._n - a._n*b._n + b._n*b._n)/(n*n*n)
+ 6*d2*(a._n*a._n*b._m2 + b._n*b._n*a._m2)/(n*n) + 4*d*(a._n*b._m3 - b._n*a._m3)/n;

128
src/Numerics/Statistics/Statistics.cs

@ -91,7 +91,7 @@ namespace MathNet.Numerics.Statistics
}
/// <summary>
/// Estimates the sample mean.
/// Evaluates the sample mean, an estimate of the population mean.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The data to calculate the mean of.</param>
@ -105,7 +105,7 @@ namespace MathNet.Numerics.Statistics
}
/// <summary>
/// Estimates the sample mean.
/// Evaluates the sample mean, an estimate of the population mean.
/// Returns NaN if data is empty or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>
@ -143,7 +143,7 @@ namespace MathNet.Numerics.Statistics
}
/// <summary>
/// Evaluates the population variance from the provided full population.
/// Evaluates the variance from the provided full population.
/// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
@ -157,7 +157,7 @@ namespace MathNet.Numerics.Statistics
}
/// <summary>
/// Evaluates the population variance from the provided full population.
/// Evaluates the variance from the provided full population.
/// On a dataset of size N will use an N normalize and would thus be biased if applied to a subsetr.
/// Returns NaN if data is empty or if any entry is NaN.
/// Null-entries are ignored.
@ -195,7 +195,7 @@ namespace MathNet.Numerics.Statistics
}
/// <summary>
/// Evaluates the population standard deviation from the provided full population.
/// Evaluates the standard deviation from the provided full population.
/// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
@ -209,7 +209,7 @@ namespace MathNet.Numerics.Statistics
}
/// <summary>
/// Evaluates the population standard deviation from the provided full population.
/// Evaluates the standard deviation from the provided full population.
/// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
/// Returns NaN if data is empty or if any entry is NaN.
/// Null-entries are ignored.
@ -220,6 +220,98 @@ namespace MathNet.Numerics.Statistics
return StreamingStatistics.PopulationStandardDeviation(population.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
/// Estimates the unbiased population skewness from the provided samples.
/// Uses a normalizer (Bessel's correction; type 2).
/// Returns NaN if data has less than three entries or if any entry is NaN.
/// </summary>
/// <param name="samples">A subset of samples, sampled from the full population.</param>
public static double Skewness(this IEnumerable<double> samples)
{
return new RunningStatistics(samples).Skewness;
}
/// <summary>
/// Estimates the unbiased population skewness from the provided samples.
/// Uses a normalizer (Bessel's correction; type 2).
/// Returns NaN if data has less than three entries or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>
/// <param name="samples">A subset of samples, sampled from the full population.</param>
public static double Skewness(this IEnumerable<double?> samples)
{
return new RunningStatistics(samples.Where(d => d.HasValue).Select(d => d.Value)).Skewness;
}
/// <summary>
/// Evaluates the skewness from the full population.
/// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
/// Returns NaN if data has less than two entries or if any entry is NaN.
/// </summary>
/// <param name="population">The full population data.</param>
public static double PopulationSkewness(this IEnumerable<double> population)
{
return new RunningStatistics(population).PopulationSkewness;
}
/// <summary>
/// Evaluates the skewness from the full population.
/// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
/// Returns NaN if data has less than two entries or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>
/// <param name="population">The full population data.</param>
public static double PopulationSkewness(this IEnumerable<double?> population)
{
return new RunningStatistics(population.Where(d => d.HasValue).Select(d => d.Value)).PopulationSkewness;
}
/// <summary>
/// Estimates the unbiased population kurtosis from the provided samples.
/// Uses a normalizer (Bessel's correction; type 2).
/// Returns NaN if data has less than four entries or if any entry is NaN.
/// </summary>
/// <param name="samples">A subset of samples, sampled from the full population.</param>
public static double Kurtosis(this IEnumerable<double> samples)
{
return new RunningStatistics(samples).Kurtosis;
}
/// <summary>
/// Estimates the unbiased population kurtosis from the provided samples.
/// Uses a normalizer (Bessel's correction; type 2).
/// Returns NaN if data has less than four entries or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>
/// <param name="samples">A subset of samples, sampled from the full population.</param>
public static double Kurtosis(this IEnumerable<double?> samples)
{
return new RunningStatistics(samples.Where(d => d.HasValue).Select(d => d.Value)).Kurtosis;
}
/// <summary>
/// Evaluates the kurtosis from the full population.
/// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
/// Returns NaN if data has less than three entries or if any entry is NaN.
/// </summary>
/// <param name="population">The full population data.</param>
public static double PopulationKurtosis(this IEnumerable<double> population)
{
return new RunningStatistics(population).PopulationKurtosis;
}
/// <summary>
/// Evaluates the kurtosis from the full population.
/// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
/// Returns NaN if data has less than three entries or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>
/// <param name="population">The full population data.</param>
public static double PopulationKurtosis(this IEnumerable<double?> population)
{
return new RunningStatistics(population.Where(d => d.HasValue).Select(d => d.Value)).PopulationKurtosis;
}
/// <summary>
/// Estimates the sample mean and the unbiased population variance from the provided samples.
/// On a dataset of size N will use an N-1 normalizer (Bessel's correction).
@ -250,6 +342,28 @@ namespace MathNet.Numerics.Statistics
: StreamingStatistics.MeanStandardDeviation(samples);
}
/// <summary>
/// Estimates the unbiased population skewness and kurtosis from the provided samples in a single pass.
/// Uses a normalizer (Bessel's correction; type 2).
/// </summary>
/// <param name="samples">A subset of samples, sampled from the full population.</param>
public static Tuple<double, double> SkewnessKurtosis(this IEnumerable<double> samples)
{
var stats = new RunningStatistics(samples);
return new Tuple<double, double>(stats.Skewness, stats.Kurtosis);
}
/// <summary>
/// Evaluates the skewness and kurtosis from the full population.
/// Does not use a normalizer and would thus be biased if applied to a subset (type 1).
/// </summary>
/// <param name="population">The full population data.</param>
public static Tuple<double, double> PopulationSkewnessKurtosis(this IEnumerable<double> population)
{
var stats = new RunningStatistics(population);
return new Tuple<double, double>(stats.PopulationSkewness, stats.PopulationKurtosis);
}
/// <summary>
/// Estimates the unbiased population covariance from the provided samples.
/// On a dataset of size N will use an N-1 normalizer (Bessel's correction).
@ -297,7 +411,7 @@ namespace MathNet.Numerics.Statistics
/// <summary>
/// Evaluates the population covariance from the provided full populations.
/// On a dataset of size N will use an N normalize and would thus be biased if applied to a subsetr.
/// On a dataset of size N will use an N normalize and would thus be biased if applied to a subset.
/// Returns NaN if data is empty or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>

62
src/UnitTests/StatisticsTests/RunningStatisticsTests.cs

@ -28,6 +28,10 @@
// OTHER DEALINGS IN THE SOFTWARE.
// </copyright>
using System.Linq;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Random;
namespace MathNet.Numerics.UnitTests.StatisticsTests
{
#if !PORTABLE
@ -165,6 +169,64 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(stats.Skewness, Is.NaN);
Assert.That(stats.Kurtosis, Is.NaN);
}
[Test]
public void Combine()
{
var rnd = new SystemRandomSource(10);
var a = Generate.Random(200, new Erlang(2, 0.2, rnd));
var b = Generate.Random(100, new Beta(1.2, 1.4, rnd));
var c = Generate.Random(150, new Rayleigh(0.8, rnd));
var d = a.Concat(b).Concat(c).ToArray();
var x = new RunningStatistics(d);
var y = new RunningStatistics(a);
y.PushRange(b);
y.PushRange(c);
var za = new RunningStatistics(a);
var zb = new RunningStatistics(b);
var zc = new RunningStatistics(c);
var z = za + zb + zc;
Assert.That(x.Mean, Is.EqualTo(d.Mean()).Within(1e-12), "Mean Reference");
Assert.That(y.Mean, Is.EqualTo(x.Mean).Within(1e-12), "Mean y");
Assert.That(z.Mean, Is.EqualTo(x.Mean).Within(1e-12), "Mean z");
Assert.That(x.Variance, Is.EqualTo(d.Variance()).Within(1e-12), "Variance Reference");
Assert.That(y.Variance, Is.EqualTo(x.Variance).Within(1e-12), "Variance y");
Assert.That(z.Variance, Is.EqualTo(x.Variance).Within(1e-12), "Variance z");
Assert.That(x.PopulationVariance, Is.EqualTo(d.PopulationVariance()).Within(1e-12), "PopulationVariance Reference");
Assert.That(y.PopulationVariance, Is.EqualTo(x.PopulationVariance).Within(1e-12), "PopulationVariance y");
Assert.That(z.PopulationVariance, Is.EqualTo(x.PopulationVariance).Within(1e-12), "PopulationVariance z");
Assert.That(x.StandardDeviation, Is.EqualTo(d.StandardDeviation()).Within(1e-12), "StandardDeviation Reference");
Assert.That(y.StandardDeviation, Is.EqualTo(x.StandardDeviation).Within(1e-12), "StandardDeviation y");
Assert.That(z.StandardDeviation, Is.EqualTo(x.StandardDeviation).Within(1e-12), "StandardDeviation z");
Assert.That(x.PopulationStandardDeviation, Is.EqualTo(d.PopulationStandardDeviation()).Within(1e-12), "PopulationStandardDeviation Reference");
Assert.That(y.PopulationStandardDeviation, Is.EqualTo(x.PopulationStandardDeviation).Within(1e-12), "PopulationStandardDeviation y");
Assert.That(z.PopulationStandardDeviation, Is.EqualTo(x.PopulationStandardDeviation).Within(1e-12), "PopulationStandardDeviation z");
Assert.That(x.Skewness, Is.EqualTo(d.Skewness()).Within(1e-12), "Skewness Reference (not independent!)");
Assert.That(y.Skewness, Is.EqualTo(x.Skewness).Within(1e-12), "Skewness y");
Assert.That(z.Skewness, Is.EqualTo(x.Skewness).Within(1e-12), "Skewness z");
Assert.That(x.PopulationSkewness, Is.EqualTo(d.PopulationSkewness()).Within(1e-12), "PopulationSkewness Reference (not independent!)");
Assert.That(y.PopulationSkewness, Is.EqualTo(x.PopulationSkewness).Within(1e-12), "PopulationSkewness y");
Assert.That(z.PopulationSkewness, Is.EqualTo(x.PopulationSkewness).Within(1e-12), "PopulationSkewness z");
Assert.That(x.Kurtosis, Is.EqualTo(d.Kurtosis()).Within(1e-12), "Kurtosis Reference (not independent!)");
Assert.That(y.Kurtosis, Is.EqualTo(x.Kurtosis).Within(1e-12), "Kurtosis y");
Assert.That(z.Kurtosis, Is.EqualTo(x.Kurtosis).Within(1e-12), "Kurtosis z");
Assert.That(x.PopulationKurtosis, Is.EqualTo(d.PopulationKurtosis()).Within(1e-12), "PopulationKurtosis Reference (not independent!)");
Assert.That(y.PopulationKurtosis, Is.EqualTo(x.PopulationKurtosis).Within(1e-12), "PopulationKurtosis y");
Assert.That(z.PopulationKurtosis, Is.EqualTo(x.PopulationKurtosis).Within(1e-12), "PopulationKurtosis z");
}
}
#endif
}

Loading…
Cancel
Save