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 @@
+