From 8334454fad9f6fe2a30a669b798e5032297c14ae Mon Sep 17 00:00:00 2001 From: Ethar Alali Date: Tue, 5 Nov 2013 00:05:14 +0000 Subject: [PATCH] Added RSquared class (and test - in TD like you mean it style) to the project. --- src/Numerics/GoodnessOfFit/RSquared.cs | 45 +++++++++++++ src/Numerics/Numerics.csproj | 2 + src/UnitTests/GoodnessOfFit/RSquaredTest.cs | 73 +++++++++++++++++++++ src/UnitTests/UnitTests.csproj | 1 + 4 files changed, 121 insertions(+) create mode 100644 src/Numerics/GoodnessOfFit/RSquared.cs create mode 100644 src/UnitTests/GoodnessOfFit/RSquaredTest.cs diff --git a/src/Numerics/GoodnessOfFit/RSquared.cs b/src/Numerics/GoodnessOfFit/RSquared.cs new file mode 100644 index 00000000..4414b69f --- /dev/null +++ b/src/Numerics/GoodnessOfFit/RSquared.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using MathNet.Numerics.LinearAlgebra.Double; + +namespace MathNet.Numerics.GoodnessOfFit +{ + public class RSquared + { + /// + /// Calculated the R-Squared value given modelled and observed values + /// + /// The values expected from the modelled + /// The actual data set values obtained + /// + public static double RSqr(IEnumerable modelledValues, IEnumerable observedValues) + { + var modelledData = modelledValues as double[] ?? modelledValues.ToArray(); + var observedData = observedValues as double[] ?? observedValues.ToArray(); + var observedDataCount = observedData.Count(); + if ( modelledData.Count() != observedDataCount) + { + throw new ArgumentException("Dataset length mismatch"); + } + + var observedSum = observedData.Sum(); + var modelledSum = modelledData.Sum(); + + var sumObservedByModelled = 0d; + + for (var itemIndex = 0; itemIndex < observedDataCount; itemIndex++) + { + sumObservedByModelled += (observedData[itemIndex] * modelledData[itemIndex]); + } + + var sumObservedSquared = observedData.Sum(item => item * item); + var sumModelledSquared = modelledData.Sum(item => item * item); + + return Math.Pow(( observedDataCount * sumObservedByModelled - observedSum * modelledSum ) / + Math.Sqrt((observedDataCount * sumObservedSquared - Math.Pow(observedSum, 2)) + * (observedDataCount * sumModelledSquared - Math.Pow(modelledSum, 2))), 2); + } + } +} diff --git a/src/Numerics/Numerics.csproj b/src/Numerics/Numerics.csproj index 00054cff..ff06c46e 100644 --- a/src/Numerics/Numerics.csproj +++ b/src/Numerics/Numerics.csproj @@ -87,6 +87,7 @@ + @@ -439,5 +440,6 @@ Designer + \ No newline at end of file diff --git a/src/UnitTests/GoodnessOfFit/RSquaredTest.cs b/src/UnitTests/GoodnessOfFit/RSquaredTest.cs new file mode 100644 index 00000000..33efb930 --- /dev/null +++ b/src/UnitTests/GoodnessOfFit/RSquaredTest.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using MathNet.Numerics.GoodnessOfFit; +using NUnit.Framework; + +namespace MathNet.Numerics.UnitTests.GoodnessOfFit +{ + [TestFixture] + public class RSquaredTest + { + /// + /// Test the R-squared value of a values with itself + /// + [Test] + public void WhenCalculatingRSquaredOfLinearDistributionWithItselfThenRSquaredIsOne() + { + var data = new List(); + for (int i = 1; i <= 10; i++) + data.Add(i); + + Assert.That(RSquared.RSqr(data, data), Is.EqualTo(1)); + } + + [Test] + [ExpectedException(typeof(ArgumentException))] + public void WhenGivenTwoDatasetsOfDifferentSizeThenThrowsArgumentException() + { + var observedData = new List() + { + 23 + ,9 + ,5 + ,7 + ,10 + ,5 + ,4 + ,1 + ,2 + ,1 + }; + + var modelledData = new List() + { + 8 + ,9 + ,10 + }; + + RSquared.RSqr(modelledData, observedData); + + Assert.Fail("Expected ArgumentException exception wasn't thrown"); + } + + [Test] + public void WhenCalculatingRSquaredOfUnevenDistributionWithLInearDistributionThenRSquaredIsCalculated() + { + var observedData = new List() + { + 1, 2.3, 3.1, 4.8, 5.6, 6.3 + }; + + var modelledData = new List() + { + 2.6, 2.8, 3.1, 4.7, 5.1, 5.3 + }; + + Assert.That(Math.Round(RSquared.RSqr(modelledData, observedData), 11), Is.EqualTo(Math.Round(0.94878520708673d, 11))); + } + } +} diff --git a/src/UnitTests/UnitTests.csproj b/src/UnitTests/UnitTests.csproj index 271014d2..e0868287 100644 --- a/src/UnitTests/UnitTests.csproj +++ b/src/UnitTests/UnitTests.csproj @@ -133,6 +133,7 @@ +