Browse Source

Add Spearman Rank Correlation Coefficient

More more info see
https://en.wikipedia.org/wiki/Spearman_rank_correlation
pull/123/merge
Iain McDonald 13 years ago
committed by Christoph Ruegg
parent
commit
3af161b168
  1. 6
      src/Examples/Statistics.cs
  2. 44
      src/Numerics/Statistics/Correlation.cs
  3. 26
      src/UnitTests/StatisticsTests/CorrelationTests.cs

6
src/Examples/Statistics.cs

@ -77,7 +77,7 @@ namespace Examples
Console.WriteLine(@"{0} - Standard deviation", chiSquare.StdDev.ToString(" #0.00000;-#0.00000"));
Console.WriteLine(@"{0} - Skewness", chiSquare.Skewness.ToString(" #0.00000;-#0.00000"));
Console.WriteLine();
// 2. Generate 1000 samples of the ChiSquare(5) distribution
Console.WriteLine(@"2. Generate 1000 samples of the ChiSquare(5) distribution");
var data = new double[1000];
@ -120,12 +120,14 @@ namespace Examples
// 5. Correlation coefficient between 1000 samples of ChiSquare(5) and ChiSquare(2.5)
Console.WriteLine(@"5. Correlation coefficient between 1000 samples of ChiSquare(5) and ChiSquare(2.5) is {0}", Correlation.Pearson(data, dataB).ToString("N04"));
Console.WriteLine(@"6. Ranked correlation coefficient between 1000 samples of ChiSquare(5) and ChiSquare(2.5) is {0}", Correlation.Spearman(data, dataB).ToString("N04"));
Console.WriteLine();
// 6. Correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x
data = SignalGenerator.EquidistantInterval(x => x * 2, 0, 100, 1000);
dataB = SignalGenerator.EquidistantInterval(x => x * x, 0, 100, 1000);
Console.WriteLine(@"6. Correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x is {0}", Correlation.Pearson(data, dataB).ToString("N04"));
Console.WriteLine(@"7. Correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x is {0}", Correlation.Pearson(data, dataB).ToString("N04"));
Console.WriteLine(@"8. Ranked correlation coefficient between 1000 samples of f(x) = x * 2 and f(x) = x * x is {0}", Correlation.Spearman(data, dataB).ToString("N04"));
Console.WriteLine();
}
}

44
src/Numerics/Statistics/Correlation.cs

@ -32,7 +32,7 @@ namespace MathNet.Numerics.Statistics
{
using System;
using System.Collections.Generic;
using Properties;
using System.Linq;
/// <summary>
/// A class with correlation measures between two datasets.
@ -88,5 +88,47 @@ namespace MathNet.Numerics.Statistics
return r / Math.Sqrt(varA * varB);
}
/// <summary>
/// Computes the Spearman Ranked Correlation Coefficient.
/// </summary>
/// <param name="dataA">Sample data series A.</param>
/// <param name="dataB">Sample data series B.</param>
/// <returns>The Spearman Ranked Correlation Coefficient.</returns>
public static double Spearman(IEnumerable<double> dataA, IEnumerable<double> dataB)
{
return Pearson(RankedSeries(dataA.ToList()), RankedSeries(dataB.ToList()));
}
private static IEnumerable<double> RankedSeries(ICollection<double> series)
{
if (series == null || series.Count == 0)
return Enumerable.Empty<double>();
var rankedSamples = series.Select((sample, index) => new { Sample = sample, RankIndex = index }).OrderBy(s => s.Sample).ToList();
var rankedArray = new double[series.Count];
var previousSample = rankedSamples.Select((sampleIndex, index) => new { SampleIndex = sampleIndex, LoopIndex = index }).First();
foreach (var rankedSampleIndex in rankedSamples.Select((sampleIndex, index) => new { SampleIndex = sampleIndex, LoopIndex = index }))
{
var currentSample = rankedSampleIndex;
if (Math.Abs(currentSample.SampleIndex.Sample - previousSample.SampleIndex.Sample) <= 0)
continue;
var rankedValue = (currentSample.LoopIndex + previousSample.LoopIndex - 1) / 2d + 1;
foreach (var index in Enumerable.Range(previousSample.LoopIndex, currentSample.LoopIndex - previousSample.LoopIndex))
rankedArray[rankedSamples[index].RankIndex] = rankedValue;
previousSample = currentSample;
}
var finalValue = (rankedSamples.Count + previousSample.LoopIndex - 1) / 2d + 1;
foreach (var index in Enumerable.Range(previousSample.LoopIndex, rankedSamples.Count - previousSample.LoopIndex))
rankedArray[rankedSamples[index].RankIndex] = finalValue;
return rankedArray;
}
}
}

26
src/UnitTests/StatisticsTests/CorrelationTests.cs

@ -71,7 +71,7 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
var dataB = _data["lew"].Data.Take(200);
var corr = Correlation.Pearson(dataA, dataB);
AssertHelpers.AlmostEqual(corr, -0.029470861580726, 13);
AssertHelpers.AlmostEqual(-0.029470861580726, corr, 13);
}
/// <summary>
@ -84,6 +84,30 @@ namespace MathNet.Numerics.UnitTests.StatisticsTests
var dataB = _data["lew"].Data;
Assert.Throws<ArgumentOutOfRangeException>(() => Correlation.Pearson(dataA, dataB));
}
/// <summary>
/// Spearman correlation test.
/// </summary>
[Test]
public void SpearmanCorrelationTest()
{
var dataA = _data["lottery"].Data.Take(200);
var dataB = _data["lew"].Data.Take(200);
var corr = Correlation.Spearman(dataA, dataB);
AssertHelpers.AlmostEqual(-0.0382856977898528, corr, 13);
}
/// <summary>
/// Spearman correlation test fail.
/// </summary>
[Test]
public void SpearmanCorrelationTestFail()
{
var dataA = _data["lottery"].Data;
var dataB = _data["lew"].Data;
Assert.Throws<ArgumentOutOfRangeException>(() => Correlation.Spearman(dataA, dataB));
}
}
#endif
}

Loading…
Cancel
Save