Browse Source

Statistics: mean of empty set should be NaN

v2
Christoph Ruegg 14 years ago
parent
commit
e1cf1cc7e6
  1. 180
      src/Numerics/Statistics/Statistics.cs
  2. 4
      src/Numerics/Statistics/StreamingStatistics.cs
  3. 11
      src/UnitTests/StatisticsTests/StatisticsTests.cs

180
src/Numerics/Statistics/Statistics.cs

@ -40,6 +40,53 @@ namespace MathNet.Numerics.Statistics
/// </summary>
public static class Statistics
{
/// <summary>
/// Returns the minimum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double Minimum(this IEnumerable<double> data)
{
var array = data as double[];
return array != null
? ArrayStatistics.Minimum(array)
: StreamingStatistics.Minimum(data);
}
/// <summary>
/// Returns the minimum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double Minimum(this IEnumerable<double?> data)
{
if (data == null) throw new ArgumentNullException("data");
return StreamingStatistics.Minimum(data.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
/// Returns the maximum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double Maximum(this IEnumerable<double> data)
{
var array = data as double[];
return array != null
? ArrayStatistics.Maximum(array)
: StreamingStatistics.Maximum(data);
}
/// <summary>
/// Returns the maximum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double Maximum(this IEnumerable<double?> data)
{
if (data == null) throw new ArgumentNullException("data");
return StreamingStatistics.Maximum(data.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
/// Calculates the sample mean.
/// </summary>
@ -47,19 +94,10 @@ namespace MathNet.Numerics.Statistics
/// <returns>The mean of the sample.</returns>
public static double Mean(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double mean = 0;
ulong m = 0;
foreach (var item in data)
{
mean += (item - mean) / ++m;
}
return mean;
var array = data as double[];
return array != null
? ArrayStatistics.Mean(array)
: StreamingStatistics.Mean(data);
}
/// <summary>
@ -69,22 +107,8 @@ namespace MathNet.Numerics.Statistics
/// <returns>The mean of the sample.</returns>
public static double Mean(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double mean = 0;
ulong m = 0;
foreach (var item in data)
{
if (item.HasValue)
{
mean += (item.Value - mean) / ++m;
}
}
return mean;
if (data == null) throw new ArgumentNullException("data");
return StreamingStatistics.Mean(data.Where(d => d.HasValue).Select(d => d.Value));
}
/// <summary>
@ -321,104 +345,6 @@ namespace MathNet.Numerics.Statistics
return Math.Sqrt(PopulationVariance(data));
}
/// <summary>
/// Returns the minimum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double Minimum(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double min = double.MaxValue;
ulong count = 0;
foreach (double? d in data)
{
if (d.HasValue)
{
min = Math.Min(min, d.Value);
count++;
}
}
return count == 0 ? double.NaN : min;
}
/// <summary>
/// Returns the maximum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double Maximum(this IEnumerable<double?> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double max = double.MinValue;
ulong count = 0;
foreach (double? d in data)
{
if (d.HasValue)
{
max = Math.Max(max, d.Value);
count++;
}
}
return count == 0 ? double.NaN : max;
}
/// <summary>
/// Returns the minimum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The minimum value in the sample data.</returns>
public static double Minimum(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double min = double.MaxValue;
ulong count = 0;
foreach (double d in data)
{
min = Math.Min(min, d);
count++;
}
return count == 0 ? double.NaN : min;
}
/// <summary>
/// Returns the maximum value in the sample data.
/// </summary>
/// <param name="data">The sample data.</param>
/// <returns>The maximum value in the sample data.</returns>
public static double Maximum(this IEnumerable<double> data)
{
if (data == null)
{
throw new ArgumentNullException("data");
}
double max = double.MinValue;
ulong count = 0;
foreach (double d in data)
{
max = Math.Max(max, d);
count++;
}
return count == 0 ? double.NaN : max;
}
/// <summary>
/// Calculates the sample median.
/// </summary>

4
src/Numerics/Statistics/StreamingStatistics.cs

@ -90,11 +90,13 @@ namespace MathNet.Numerics.Statistics
double mean = 0;
ulong m = 0;
bool any = false;
foreach (var d in stream)
{
mean += (d - mean) / ++m;
any = true;
}
return mean;
return any ? mean : double.NaN;
}
}
}

11
src/UnitTests/StatisticsTests/StatisticsTests.cs

@ -261,6 +261,17 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
Assert.That(StreamingStatistics.Maximum(new[] { 2d }), Is.Not.NaN);
}
[Test]
public void MeanOfEmptyMustBeNaN()
{
Assert.That(Statistics.Mean(new double[0]), Is.NaN);
Assert.That(Statistics.Mean(new[] { 2d }), Is.Not.NaN);
Assert.That(ArrayStatistics.Mean(new double[0]), Is.NaN);
Assert.That(ArrayStatistics.Mean(new[] { 2d }), Is.Not.NaN);
Assert.That(StreamingStatistics.Mean(new double[0]), Is.NaN);
Assert.That(StreamingStatistics.Mean(new[] { 2d }), Is.Not.NaN);
}
[Test]
public void SampleVarianceOfEmptyAndSingleMustBeNaN()
{

Loading…
Cancel
Save