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> /// </summary>
public static class Statistics 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> /// <summary>
/// Calculates the sample mean. /// Calculates the sample mean.
/// </summary> /// </summary>
@ -47,19 +94,10 @@ namespace MathNet.Numerics.Statistics
/// <returns>The mean of the sample.</returns> /// <returns>The mean of the sample.</returns>
public static double Mean(this IEnumerable<double> data) public static double Mean(this IEnumerable<double> data)
{ {
if (data == null) var array = data as double[];
{ return array != null
throw new ArgumentNullException("data"); ? ArrayStatistics.Mean(array)
} : StreamingStatistics.Mean(data);
double mean = 0;
ulong m = 0;
foreach (var item in data)
{
mean += (item - mean) / ++m;
}
return mean;
} }
/// <summary> /// <summary>
@ -69,22 +107,8 @@ namespace MathNet.Numerics.Statistics
/// <returns>The mean of the sample.</returns> /// <returns>The mean of the sample.</returns>
public static double Mean(this IEnumerable<double?> data) public static double Mean(this IEnumerable<double?> data)
{ {
if (data == null) if (data == null) throw new ArgumentNullException("data");
{ return StreamingStatistics.Mean(data.Where(d => d.HasValue).Select(d => d.Value));
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;
} }
/// <summary> /// <summary>
@ -321,104 +345,6 @@ namespace MathNet.Numerics.Statistics
return Math.Sqrt(PopulationVariance(data)); 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> /// <summary>
/// Calculates the sample median. /// Calculates the sample median.
/// </summary> /// </summary>

4
src/Numerics/Statistics/StreamingStatistics.cs

@ -90,11 +90,13 @@ namespace MathNet.Numerics.Statistics
double mean = 0; double mean = 0;
ulong m = 0; ulong m = 0;
bool any = false;
foreach (var d in stream) foreach (var d in stream)
{ {
mean += (d - mean) / ++m; 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); 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] [Test]
public void SampleVarianceOfEmptyAndSingleMustBeNaN() public void SampleVarianceOfEmptyAndSingleMustBeNaN()
{ {

Loading…
Cancel
Save