forked from tsai/mathnet-numerics
committed by
Christoph Ruegg
4 changed files with 121 additions and 0 deletions
@ -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 |
|||
{ |
|||
/// <summary>
|
|||
/// Calculated the R-Squared value given modelled and observed values
|
|||
/// </summary>
|
|||
/// <param name="modelledValues">The values expected from the modelled</param>
|
|||
/// <param name="observedValues">The actual data set values obtained</param>
|
|||
/// <returns></returns>
|
|||
public static double RSqr(IEnumerable<double> modelledValues, IEnumerable<double> 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); |
|||
} |
|||
} |
|||
} |
|||
@ -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 |
|||
{ |
|||
/// <summary>
|
|||
/// Test the R-squared value of a values with itself
|
|||
/// </summary>
|
|||
[Test] |
|||
public void WhenCalculatingRSquaredOfLinearDistributionWithItselfThenRSquaredIsOne() |
|||
{ |
|||
var data = new List<double>(); |
|||
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<double>() |
|||
{ |
|||
23 |
|||
,9 |
|||
,5 |
|||
,7 |
|||
,10 |
|||
,5 |
|||
,4 |
|||
,1 |
|||
,2 |
|||
,1 |
|||
}; |
|||
|
|||
var modelledData = new List<double>() |
|||
{ |
|||
8 |
|||
,9 |
|||
,10 |
|||
}; |
|||
|
|||
RSquared.RSqr(modelledData, observedData); |
|||
|
|||
Assert.Fail("Expected ArgumentException exception wasn't thrown"); |
|||
} |
|||
|
|||
[Test] |
|||
public void WhenCalculatingRSquaredOfUnevenDistributionWithLInearDistributionThenRSquaredIsCalculated() |
|||
{ |
|||
var observedData = new List<double>() |
|||
{ |
|||
1, 2.3, 3.1, 4.8, 5.6, 6.3 |
|||
}; |
|||
|
|||
var modelledData = new List<double>() |
|||
{ |
|||
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))); |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue