diff --git a/src/Numerics/Statistics/RunningStatistics.cs b/src/Numerics/Statistics/RunningStatistics.cs
index bb5746e4..6af0bf9b 100644
--- a/src/Numerics/Statistics/RunningStatistics.cs
+++ b/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;
diff --git a/src/Numerics/Statistics/Statistics.cs b/src/Numerics/Statistics/Statistics.cs
index 6cd3fa0f..b687310e 100644
--- a/src/Numerics/Statistics/Statistics.cs
+++ b/src/Numerics/Statistics/Statistics.cs
@@ -91,7 +91,7 @@ namespace MathNet.Numerics.Statistics
}
///
- /// 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.
///
/// The data to calculate the mean of.
@@ -105,7 +105,7 @@ namespace MathNet.Numerics.Statistics
}
///
- /// 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.
///
@@ -143,7 +143,7 @@ namespace MathNet.Numerics.Statistics
}
///
- /// 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.
///
@@ -157,7 +157,7 @@ namespace MathNet.Numerics.Statistics
}
///
- /// 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
}
///
- /// 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.
///
@@ -209,7 +209,7 @@ namespace MathNet.Numerics.Statistics
}
///
- /// 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));
}
+ ///
+ /// 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.
+ ///
+ /// A subset of samples, sampled from the full population.
+ public static double Skewness(this IEnumerable samples)
+ {
+ return new RunningStatistics(samples).Skewness;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// A subset of samples, sampled from the full population.
+ public static double Skewness(this IEnumerable samples)
+ {
+ return new RunningStatistics(samples.Where(d => d.HasValue).Select(d => d.Value)).Skewness;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The full population data.
+ public static double PopulationSkewness(this IEnumerable population)
+ {
+ return new RunningStatistics(population).PopulationSkewness;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The full population data.
+ public static double PopulationSkewness(this IEnumerable population)
+ {
+ return new RunningStatistics(population.Where(d => d.HasValue).Select(d => d.Value)).PopulationSkewness;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// A subset of samples, sampled from the full population.
+ public static double Kurtosis(this IEnumerable samples)
+ {
+ return new RunningStatistics(samples).Kurtosis;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// A subset of samples, sampled from the full population.
+ public static double Kurtosis(this IEnumerable samples)
+ {
+ return new RunningStatistics(samples.Where(d => d.HasValue).Select(d => d.Value)).Kurtosis;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The full population data.
+ public static double PopulationKurtosis(this IEnumerable population)
+ {
+ return new RunningStatistics(population).PopulationKurtosis;
+ }
+
+ ///
+ /// 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.
+ ///
+ /// The full population data.
+ public static double PopulationKurtosis(this IEnumerable population)
+ {
+ return new RunningStatistics(population.Where(d => d.HasValue).Select(d => d.Value)).PopulationKurtosis;
+ }
+
///
/// 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);
}
+ ///
+ /// Estimates the unbiased population skewness and kurtosis from the provided samples in a single pass.
+ /// Uses a normalizer (Bessel's correction; type 2).
+ ///
+ /// A subset of samples, sampled from the full population.
+ public static Tuple SkewnessKurtosis(this IEnumerable samples)
+ {
+ var stats = new RunningStatistics(samples);
+ return new Tuple(stats.Skewness, stats.Kurtosis);
+ }
+
+ ///
+ /// 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).
+ ///
+ /// The full population data.
+ public static Tuple PopulationSkewnessKurtosis(this IEnumerable population)
+ {
+ var stats = new RunningStatistics(population);
+ return new Tuple(stats.PopulationSkewness, stats.PopulationKurtosis);
+ }
+
///
/// 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
///
/// 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.
///
diff --git a/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs b/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs
index cc8e7d03..bb87c8c4 100644
--- a/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs
+++ b/src/UnitTests/StatisticsTests/RunningStatisticsTests.cs
@@ -28,6 +28,10 @@
// OTHER DEALINGS IN THE SOFTWARE.
//
+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
}