Browse Source

Statistics: RootMeanSquare (RMS)

pull/248/head
Christoph Ruegg 12 years ago
parent
commit
a7acebfe3a
  1. 11
      src/Numerics/Distance.cs
  2. 24
      src/Numerics/Statistics/ArrayStatistics.cs
  3. 26
      src/Numerics/Statistics/Statistics.cs
  4. 22
      src/Numerics/Statistics/StreamingStatistics.cs
  5. 33
      src/UnitTests/StatisticsTests/StatisticsTests.cs

11
src/Numerics/Distance.cs

@ -3,9 +3,9 @@
// http://numerics.mathdotnet.com
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
//
// Copyright (c) 2009-2013 Math.NET
//
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
@ -14,10 +14,10 @@
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@ -36,6 +36,9 @@ using MathNet.Numerics.Statistics;
namespace MathNet.Numerics
{
/// <summary>
/// Metrics to measure the distance between two structures.
/// </summary>
public static class Distance
{
/// <summary>

24
src/Numerics/Statistics/ArrayStatistics.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -317,6 +317,28 @@ namespace MathNet.Numerics.Statistics
return covariance/population1.Length;
}
/// <summary>
/// Estimates the root mean square (RMS) also known as quadratic mean from the unsorted data array.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="data">Sample array, no sorting is assumed.</param>
public static double RootMeanSquare(double[] data)
{
if (data.Length == 0)
{
return double.NaN;
}
double mean = 0;
ulong m = 0;
for (int i = 0; i < data.Length; i++)
{
mean += (data[i]*data[i] - mean)/++m;
}
return Math.Sqrt(mean);
}
/// <summary>
/// Returns the order statistic (order 1..N) from the unsorted data array.
/// WARNING: Works inplace and can thus causes the data array to be reordered.

26
src/Numerics/Statistics/Statistics.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -423,6 +423,30 @@ namespace MathNet.Numerics.Statistics
return StreamingStatistics.PopulationCovariance(population1.Where(d => d.HasValue).Select(d => d.Value), population2.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
/// Evaluates the root mean square (RMS) also known as quadratic mean.
/// Returns NaN if data is empty or if any entry is NaN.
/// </summary>
/// <param name="data">The data to calculate the RMS of.</param>
public static double RootMeanSquare(this IEnumerable<double> data)
{
var array = data as double[];
return array != null
? ArrayStatistics.RootMeanSquare(array)
: StreamingStatistics.RootMeanSquare(data);
}
/// <summary>
/// Evaluates the root mean square (RMS) also known as quadratic mean.
/// Returns NaN if data is empty or if any entry is NaN.
/// Null-entries are ignored.
/// </summary>
/// <param name="data">The data to calculate the mean of.</param>
public static double RootMeanSquare(this IEnumerable<double?> data)
{
return StreamingStatistics.RootMeanSquare(data.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
/// Estimates the sample median from the provided samples (R8).
/// </summary>

22
src/Numerics/Statistics/StreamingStatistics.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -328,6 +328,26 @@ namespace MathNet.Numerics.Statistics
return comoment/n;
}
/// <summary>
/// Estimates the root mean square (RMS) also known as quadratic mean from the enumerable, in a single pass without memoization.
/// Returns NaN if data is empty or any entry is NaN.
/// </summary>
/// <param name="stream">Sample stream, no sorting is assumed.</param>
public static double RootMeanSquare(IEnumerable<double> stream)
{
double mean = 0;
ulong m = 0;
bool any = false;
foreach (var d in stream)
{
mean += (d*d - mean)/++m;
any = true;
}
return any ? Math.Sqrt(mean) : double.NaN;
}
/// <summary>
/// Calculates the entropy of a stream of double values.
/// Returns NaN if any of the values in the stream are NaN.

33
src/UnitTests/StatisticsTests/StatisticsTests.cs

@ -4,7 +4,7 @@
// http://github.com/mathnet/mathnet-numerics
// http://mathnetnumerics.codeplex.com
//
// Copyright (c) 2009-2013 Math.NET
// Copyright (c) 2009-2014 Math.NET
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
@ -78,6 +78,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(() => Statistics.PopulationStandardDeviation(data), Throws.Exception);
Assert.That(() => Statistics.Covariance(data, data), Throws.Exception);
Assert.That(() => Statistics.PopulationCovariance(data, data), Throws.Exception);
Assert.That(() => Statistics.RootMeanSquare(data), Throws.Exception);
Assert.That(() => SortedArrayStatistics.Minimum(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => SortedArrayStatistics.Minimum(data), Throws.Exception.TypeOf<NullReferenceException>());
@ -103,6 +104,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(() => ArrayStatistics.PopulationStandardDeviation(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => ArrayStatistics.Covariance(data, data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => ArrayStatistics.PopulationCovariance(data, data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => ArrayStatistics.RootMeanSquare(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => ArrayStatistics.MedianInplace(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => ArrayStatistics.QuantileInplace(data, 0.3), Throws.Exception.TypeOf<NullReferenceException>());
@ -115,6 +117,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(() => StreamingStatistics.PopulationStandardDeviation(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => StreamingStatistics.Covariance(data, data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => StreamingStatistics.PopulationCovariance(data, data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => StreamingStatistics.RootMeanSquare(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => StreamingStatistics.Entropy(data), Throws.Exception.TypeOf<NullReferenceException>());
Assert.That(() => new RunningStatistics(data), Throws.Exception);
@ -138,6 +141,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => Statistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => Statistics.Covariance(data, data));
Assert.DoesNotThrow(() => Statistics.PopulationCovariance(data, data));
Assert.DoesNotThrow(() => Statistics.RootMeanSquare(data));
Assert.DoesNotThrow(() => SortedArrayStatistics.Minimum(data));
Assert.DoesNotThrow(() => SortedArrayStatistics.Maximum(data));
@ -162,6 +166,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => ArrayStatistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => ArrayStatistics.Covariance(data, data));
Assert.DoesNotThrow(() => ArrayStatistics.PopulationCovariance(data, data));
Assert.DoesNotThrow(() => ArrayStatistics.RootMeanSquare(data));
Assert.DoesNotThrow(() => ArrayStatistics.MedianInplace(data));
Assert.DoesNotThrow(() => ArrayStatistics.QuantileInplace(data, 0.3));
@ -174,6 +179,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.DoesNotThrow(() => StreamingStatistics.PopulationStandardDeviation(data));
Assert.DoesNotThrow(() => StreamingStatistics.Covariance(data, data));
Assert.DoesNotThrow(() => StreamingStatistics.PopulationCovariance(data, data));
Assert.DoesNotThrow(() => StreamingStatistics.RootMeanSquare(data));
Assert.DoesNotThrow(() => StreamingStatistics.Entropy(data));
Assert.That(() => new RunningStatistics(data), Throws.Nothing);
@ -780,14 +786,17 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
AssertHelpers.AlmostEqualRelative(1e+9, Statistics.Mean(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(4d, Statistics.Variance(gaussian.Samples().Take(10000)), 0);
AssertHelpers.AlmostEqualRelative(2d, Statistics.StandardDeviation(gaussian.Samples().Take(10000)), 1);
AssertHelpers.AlmostEqualRelative(1e+9, Statistics.RootMeanSquare(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(1e+9, ArrayStatistics.Mean(gaussian.Samples().Take(10000).ToArray()), 10);
AssertHelpers.AlmostEqualRelative(4d, ArrayStatistics.Variance(gaussian.Samples().Take(10000).ToArray()), 0);
AssertHelpers.AlmostEqualRelative(2d, ArrayStatistics.StandardDeviation(gaussian.Samples().Take(10000).ToArray()), 1);
AssertHelpers.AlmostEqualRelative(1e+9, ArrayStatistics.RootMeanSquare(gaussian.Samples().Take(10000).ToArray()), 10);
AssertHelpers.AlmostEqualRelative(1e+9, StreamingStatistics.Mean(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(4d, StreamingStatistics.Variance(gaussian.Samples().Take(10000)), 0);
AssertHelpers.AlmostEqualRelative(2d, StreamingStatistics.StandardDeviation(gaussian.Samples().Take(10000)), 1);
AssertHelpers.AlmostEqualRelative(1e+9, StreamingStatistics.RootMeanSquare(gaussian.Samples().Take(10000)), 10);
AssertHelpers.AlmostEqualRelative(1e+9, new RunningStatistics(gaussian.Samples().Take(10000)).Mean, 10);
AssertHelpers.AlmostEqualRelative(4d, new RunningStatistics(gaussian.Samples().Take(10000)).Variance, 0);
@ -852,6 +861,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(ArrayStatistics.PopulationStandardDeviation(data.Data), Is.EqualTo(StreamingStatistics.PopulationStandardDeviation(data.Data)).Within(1e-15), "PopulationStandardDeviation");
Assert.That(ArrayStatistics.Covariance(data.Data, data.Data), Is.EqualTo(StreamingStatistics.Covariance(data.Data, data.Data)).Within(1e-10), "Covariance");
Assert.That(ArrayStatistics.PopulationCovariance(data.Data, data.Data), Is.EqualTo(StreamingStatistics.PopulationCovariance(data.Data, data.Data)).Within(1e-10), "PopulationCovariance");
Assert.That(ArrayStatistics.RootMeanSquare(data.Data), Is.EqualTo(StreamingStatistics.RootMeanSquare(data.Data)).Within(1e-15), "RootMeanSquare");
}
[TestCase("lottery")]
@ -918,6 +928,17 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(new RunningStatistics(new[] { 2d }).Mean, Is.Not.NaN);
}
[Test]
public void RootMeanSquareOfEmptyMustBeNaN()
{
Assert.That(Statistics.RootMeanSquare(new double[0]), Is.NaN);
Assert.That(Statistics.RootMeanSquare(new[] { 2d }), Is.Not.NaN);
Assert.That(ArrayStatistics.RootMeanSquare(new double[0]), Is.NaN);
Assert.That(ArrayStatistics.RootMeanSquare(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.RootMeanSquare(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.RootMeanSquare(new[] { 2d }), Is.Not.NaN);
}
[Test]
public void SampleVarianceOfEmptyAndSingleMustBeNaN()
{
@ -1005,6 +1026,9 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(new DescriptiveStatistics(shorter).Mean, Is.EqualTo(0.375).Within(1e-14), "DescriptiveStatistics.Mean: shorter");
Assert.That(new DescriptiveStatistics(longer).Mean, Is.EqualTo(00.375).Within(1e-14), "DescriptiveStatistics.Mean: longer");
Assert.That(Statistics.RootMeanSquare(shorter), Is.EqualTo(Math.Sqrt(0.21875)).Within(1e-14), "Statistics.RootMeanSquare: shorter");
Assert.That(Statistics.RootMeanSquare(longer), Is.EqualTo(Math.Sqrt(0.21875)).Within(1e-14), "Statistics.RootMeanSquare: longer");
Assert.That(Statistics.Skewness(shorter), Is.EqualTo(0.0).Within(1e-12), "Statistics.Skewness: shorter");
Assert.That(Statistics.Skewness(longer), Is.EqualTo(0.0).Within(1e-12), "Statistics.Skewness: longer");
Assert.That(new DescriptiveStatistics(shorter).Skewness, Is.EqualTo(0.0).Within(1e-12), "DescriptiveStatistics.Skewness: shorter");
@ -1016,6 +1040,13 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(new DescriptiveStatistics(longer).Kurtosis, Is.EqualTo(-1.36).Within(1e-4), "DescriptiveStatistics.Kurtosis: longer");
}
[Test]
public void RootMeanSquareOfSinusoidal()
{
var data = Generate.Sinusoidal(128, 64, 16, 2.0);
Assert.That(Statistics.RootMeanSquare(data), Is.EqualTo(2.0/Constants.Sqrt2).Within(1e-12));
}
[Test]
public void EntropyIsMinimum()
{

Loading…
Cancel
Save