Skip to content

Instantly share code, notes, and snippets.

@holyketzer
Created August 26, 2013 16:47
Show Gist options
  • Save holyketzer/6343677 to your computer and use it in GitHub Desktop.
Save holyketzer/6343677 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Windows;
namespace Microsoft.SystemCenter.Visualization.Component.Extensions.Library.Controls.Web.Components
{
public class MathUtills
{
/// <summary>
/// Fits a line to a collection of (x,y) points.
/// </summary>
/// <param name="xVals">The x-axis values.</param>
/// <param name="yVals">The y-axis values.</param>
/// <param name="inclusiveStart">The inclusive inclusiveStart index.</param>
/// <param name="exclusiveEnd">The exclusive exclusiveEnd index.</param>
/// <param name="rsquared">The r^2 value of the line.</param>
/// <param name="yintercept">The y-intercept value of the line (i.e. y = ax + b, yintercept is b).</param>
/// <param name="slope">The slop of the line (i.e. y = ax + b, slope is a).</param>
public static void LinearRegression(double[] xVals, double[] yVals,
int inclusiveStart, int exclusiveEnd,
out double rsquared, out double yintercept,
out double slope)
{
Debug.Assert(xVals.Length == yVals.Length);
double sumOfX = 0;
double sumOfY = 0;
double sumOfXSq = 0;
double sumOfYSq = 0;
double ssX = 0;
double ssY = 0;
double sumCodeviates = 0;
double sCo = 0;
double count = exclusiveEnd - inclusiveStart;
for (int ctr = inclusiveStart; ctr < exclusiveEnd; ctr++)
{
double x = xVals[ctr];
double y = yVals[ctr];
sumCodeviates += x * y;
sumOfX += x;
sumOfY += y;
sumOfXSq += x * x;
sumOfYSq += y * y;
}
ssX = sumOfXSq - ((sumOfX * sumOfX) / count);
ssY = sumOfYSq - ((sumOfY * sumOfY) / count);
double RNumerator = (count * sumCodeviates) - (sumOfX * sumOfY);
double RDenom = (count * sumOfXSq - (sumOfX * sumOfX))
* (count * sumOfYSq - (sumOfY * sumOfY));
sCo = sumCodeviates - ((sumOfX * sumOfY) / count);
double meanX = sumOfX / count;
double meanY = sumOfY / count;
double dblR = RNumerator / Math.Sqrt(RDenom);
rsquared = dblR * dblR;
yintercept = meanY - ((sCo / ssX) * meanX);
slope = sCo / ssX;
}
/// <summary>
/// Get slope (a coeff) of a trend line
/// </summary>
/// <param name="points">The enumerable of points (x- and y-values).</param>
/// <returns>The slop of the line (i.e. y = ax + b, slope is a).</returns>
public static double? GetSlope(IEnumerable<Point> points)
{
double slope;
double yintercept;
double rsquared;
var cachedPoints = points.ToArray();
LinearRegression(cachedPoints.Select(p => p.X).ToArray(), cachedPoints.Select(p => p.Y).ToArray(), 0, cachedPoints.Length, out rsquared, out yintercept, out slope);
if (Double.IsNaN(slope))
{
return null;
}
return slope;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment