¿Cómo calculo una línea de tendencia para un gráfico?

Google no está siendo mi amigo. Ha pasado mucho tiempo desde mi clase de estadísticas en la universidad … Necesito calcular los puntos de inicio y final para una línea de tendencia en un gráfico. ¿Hay alguna manera fácil de hacerlo? (trabajando en C # pero sea cual sea el idioma que funcione para usted)

Dado que la línea de tendencia es recta, encuentre la pendiente eligiendo dos puntos y calculando:

(A) pendiente = (y1-y2) / (x1-x2)

Entonces necesitas encontrar el desplazamiento para la línea. La línea está especificada por la ecuación:

(B) y = desplazamiento + pendiente * x

Entonces necesitas resolver el offset. Elija cualquier punto de la línea y resuelva el desplazamiento:

(C) desplazamiento = y – (pendiente * x)

Ahora puede conectar la pendiente y la compensación en la ecuación de línea (B) y tener la ecuación que define su línea. Si su línea tiene ruido, tendrá que decidir sobre un algoritmo de promediado, o usar ajuste de curvas de algún tipo.

Si su línea no es recta, tendrá que mirar en el ajuste Curve o Least Squares Fitting : no es trivial, pero puede hacerlo. Verá los distintos tipos de ajuste de curva en la parte inferior de la página web de ajuste de mínimos cuadrados (exponencial, polinomial, etc.) si conoce el tipo de ajuste que desea.

Además, si se trata de una solución única, utilice Excel.

Gracias a todos por su ayuda. Estuve fuera de este tema por un par de días y volví a él. Pude juntar esto, no es el código más elegante, pero funciona para mis propósitos, pensé que lo compartiría si Alguien más se encuentra con este problema:

public class Statistics { public Trendline CalculateLinearRegression(int[] values) { var yAxisValues = new List(); var xAxisValues = new List(); for (int i = 0; i < values.Length; i++) { yAxisValues.Add(values[i]); xAxisValues.Add(i + 1); } return new Trendline(yAxisValues, xAxisValues); } } public class Trendline { private readonly IList xAxisValues; private readonly IList yAxisValues; private int count; private int xAxisValuesSum; private int xxSum; private int xySum; private int yAxisValuesSum; public Trendline(IList yAxisValues, IList xAxisValues) { this.yAxisValues = yAxisValues; this.xAxisValues = xAxisValues; this.Initialize(); } public int Slope { get; private set; } public int Intercept { get; private set; } public int Start { get; private set; } public int End { get; private set; } private void Initialize() { this.count = this.yAxisValues.Count; this.yAxisValuesSum = this.yAxisValues.Sum(); this.xAxisValuesSum = this.xAxisValues.Sum(); this.xxSum = 0; this.xySum = 0; for (int i = 0; i < this.count; i++) { this.xySum += (this.xAxisValues[i]*this.yAxisValues[i]); this.xxSum += (this.xAxisValues[i]*this.xAxisValues[i]); } this.Slope = this.CalculateSlope(); this.Intercept = this.CalculateIntercept(); this.Start = this.CalculateStart(); this.End = this.CalculateEnd(); } private int CalculateSlope() { try { return ((this.count*this.xySum) - (this.xAxisValuesSum*this.yAxisValuesSum))/((this.count*this.xxSum) - (this.xAxisValuesSum*this.xAxisValuesSum)); } catch (DivideByZeroException) { return 0; } } private int CalculateIntercept() { return (this.yAxisValuesSum - (this.Slope*this.xAxisValuesSum))/this.count; } private int CalculateStart() { return (this.Slope*this.xAxisValues.First()) + this.Intercept; } private int CalculateEnd() { return (this.Slope*this.xAxisValues.Last()) + this.Intercept; } } 

OK, aquí está mi mejor pseudo matemática:

La ecuación para tu línea es:

Y = a + bX

Dónde:

b = (sum (x * y) – sum (x) sum (y) / n) / (sum (x ^ 2) – sum (x) ^ 2 / n)

a = sum (y) / n – b (sum (x) / n)

Donde sum (xy) es la sum de todos los x * y etc. No muy claro, concedo, pero es lo mejor que puedo hacer sin un símbolo sigma 🙂

… y ahora con Sigma añadido

b = (Σ (xy) – (ΣxΣy) / n) / (Σ (x ^ 2) – (Σx) ^ 2 / n)

a = (Σy) / n – b ((Σx) / n)

Donde Σ (xy) es la sum de todos los x * y etc. y n es el número de puntos

Aquí hay una implementación muy rápida (y semi-sucia) de la respuesta de Bedwyr Humphreys . La interfaz también debería ser compatible con la respuesta de @matt , pero usa decimal lugar de int y usa más conceptos de IEnumerable para facilitar su uso y lectura.

Slope is b , Intercept es

 public class Trendline { public Trendline(IList yAxisValues, IList xAxisValues) : this(yAxisValues.Select((t, i) => new Tuple(xAxisValues[i], t))) { } public Trendline(IEnumerable> data) { var cachedData = data.ToList(); var n = cachedData.Count; var sumX = cachedData.Sum(x => x.Item1); var sumX2 = cachedData.Sum(x => x.Item1 * x.Item1); var sumY = cachedData.Sum(x => x.Item2); var sumXY = cachedData.Sum(x => x.Item1 * x.Item2); //b = (sum(x*y) - sum(x)sum(y)/n) // / (sum(x^2) - sum(x)^2/n) Slope = (sumXY - ((sumX * sumY) / n)) / (sumX2 - (sumX * sumX / n)); //a = sum(y)/n - b(sum(x)/n) Intercept = (sumY / n) - (Slope * (sumX / n)); Start = GetYValue(cachedData.Min(a => a.Item1)); End = GetYValue(cachedData.Max(a => a.Item1)); } public decimal Slope { get; private set; } public decimal Intercept { get; private set; } public decimal Start { get; private set; } public decimal End { get; private set; } public decimal GetYValue(decimal xValue) { return Intercept + Slope * xValue; } } 

En cuanto a una respuesta anterior

if (B) y = desplazamiento + pendiente * x

entonces (C) desplazamiento = y / (pendiente * x) es incorrecto

(C) debería ser:

desplazamiento = y- (pendiente * x)

Ver: http://zedgraph.org/wiki/index.php?title=Trend

Si tiene acceso a Excel, busque en la sección “Funciones estadísticas” de la Referencia de funciones en Ayuda. Para un mejor ajuste en línea recta, necesita SLOPE e INTERCEPT y las ecuaciones están ahí.

Oh, espera, también se definen en línea aquí: http://office.microsoft.com/en-us/excel/HP052092641033.aspx para SLOPE, y hay un enlace a INTERCEPT. Por supuesto, eso supone que MS no mueve la página, en cuyo caso prueba Google en busca de algo así como “SLEPE INTERCEPT EQUATION Excel site: microsoft.com” – el enlace dado resultó ser el tercero en este momento.

Muchas gracias por la solución, me estaba rascando la cabeza.
Así es como apliqué la solución en Excel.
Utilicé con éxito las dos funciones dadas por MUHD en Excel:
a = (sum (x * y) – sum (x) sum (y) / n) / (sum (x ^ 2) – sum (x) ^ 2 / n)
b = sum (y) / n – b (sum (x) / n)
(cuidado mi a y b son el b y a en la solución de MUHD).

– Hecho 4 columnas, por ejemplo:
NB: mis valores y valores están en B3: B17, entonces tengo n = 15;
mis valores x son 1,2,3,4 … 15.
1. Columna B: conocidos x
2. Columna C: Conocido y
3. Columna D: la línea de tendencia calculada
4. Columna E: valores B * valores C (E3 = B3 * C3, E4 = B4 * C4, …, E17 = B17 * C17)
5. Columna F: x valores al cuadrado
Luego sumo las columnas B, C y E, las sums van en la línea 18 para mí, así que tengo B18 como sum de Xs, C18 como sum de Ys, E18 como sum de X * Y y F18 como sum de cuadrados.
Para calcular a, ingrese la fórmula siguiente en cualquier celda (F35 para mí):
F35 = (E18- (B18 * C18) / 15) / (F18- (B18 * B18) / 15)
Para calcular b (en F36 para mí):
F36 = C18 / 15-F35 * (B18 / 15)
Valores de columna D, calculando la línea de tendencia de acuerdo con y = ax + b:
D3 = $ F $ 35 * B3 + $ F $ 36, D4 = $ F $ 35 * B4 + $ F $ 36 y así sucesivamente (hasta D17 para mí).

Seleccione los datos de columna (C2: D17) para hacer el gráfico.
HTH.

Esta es la forma en que calculé la pendiente: Fuente: http://classroom.synonym.com/calculate-trendline-2709.html

 class Program { public double CalculateTrendlineSlope(List graph) { int n = graph.Count; double a = 0; double b = 0; double bx = 0; double by = 0; double c = 0; double d = 0; double slope = 0; foreach (Point point in graph) { a += point.x * point.y; bx = point.x; by = point.y; c += Math.Pow(point.x, 2); d += point.x; } a *= n; b = bx * by; c *= n; d = Math.Pow(d, 2); slope = (a - b) / (c - d); return slope; } } class Point { public double x; public double y; } 

Esto es lo que terminé usando.

 public class DataPoint { public DataPoint(T1 x, T2 y) { X = x; Y = y; } [JsonProperty("x")] public T1 X { get; } [JsonProperty("y")] public T2 Y { get; } } public class Trendline { public Trendline(IEnumerable> dataPoints) { int count = 0; long sumX = 0; long sumX2 = 0; decimal sumY = 0; decimal sumXY = 0; foreach (var dataPoint in dataPoints) { count++; sumX += dataPoint.X; sumX2 += dataPoint.X * dataPoint.X; sumY += dataPoint.Y; sumXY += dataPoint.X * dataPoint.Y; } Slope = (sumXY - ((sumX * sumY) / count)) / (sumX2 - ((sumX * sumX) / count)); Intercept = (sumY / count) - (Slope * (sumX / count)); } public decimal Slope { get; private set; } public decimal Intercept { get; private set; } public decimal Start { get; private set; } public decimal End { get; private set; } public decimal GetYValue(decimal xValue) { return Slope * xValue + Intercept; } } 

Mi conjunto de datos usa una marca de tiempo Unix para el eje xy un decimal para y. Cambie esos tipos de datos para que se ajusten a sus necesidades. Hago todos los cálculos de sum en una iteración para obtener el mejor rendimiento posible.