2008-09-04 28 views
42

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 cualquiera que sea el lenguaje que funciona para usted)¿Cómo calculo una línea de tendencia para un gráfico?

Respuesta

14

Teniendo en cuenta que la línea de tendencia es recta, hallar la pendiente por la elección de dos puntos y calcular:

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

Luego debe encontrar el desplazamiento para la línea. La línea se especifica mediante la ecuación:

(B) y = desplazamiento pendiente + * x

Así que hay que resolver para su compensación. Escoja cualquier punto de la línea, y resolver para offset:

(C) offset = Y/(pendiente * x)

Ahora se puede conectar pendiente y el desplazamiento en la ecuación de la línea (B) y tienen la ecuación eso define tu 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 consultar Curve fitting, o Least Squares Fitting - no trivial, pero capaz. 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.

-Adam

+28

Estoy bastante seguro de que esto no dará como resultado una línea de tendencia ajustada; la pendiente calculada en (A) va a ser significativamente diferente dependiendo de los "dos puntos" que elija. Esta no es una línea de tendencia ajustada. –

+2

[Prefiero este que he encontrado] (http://math.stackexchange.com/questions/204020/what-is-the-equation-used-to-calculate-a-linear-trendline/204021#204021) – TecHunter

+1

@Jay Así la oración, "Si tu línea tiene ruido, tendrás que decidir sobre un algoritmo de promediado o utilizar un ajuste de curva de algún tipo". –

25

OK, aquí está mi mejor seudo matemáticas:

La ecuación para la línea es:

Y = a + bX

Dónde:

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

a = sum (y)/n - b (suma (x)/n)

Dónde suma (x) es la suma de todos los x * y etc. No es particularmente claro admito, pero es lo mejor que puedo prescindir de 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 suma de todos los x * y etc, y n es el número de puntos

+0

Esto sería una gran ayuda si pudiera averiguar lo que n representa – Praesagus

+0

La clase de matemáticas está volviendo - n es el número de puntos en un eje ¿no? – Praesagus

+0

sí, n es la cantidad de puntos que tiene. – blank

1

Si tiene acceso a Excel, busque en la sección "Funciones estadísticas" de la Referencia de funciones dentro de 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.

31

Gracias a todos por su ayuda - Estuve fuera de este tema por un par de días y volví - pude improvisar esto - no es el código más elegante, pero funciona para mis propósitos - pensé 'd cuota si alguien más se encuentra con este problema:

public class Statistics 
{ 
    public Trendline CalculateLinearRegression(int[] values) 
    { 
     var yAxisValues = new List<int>(); 
     var xAxisValues = new List<int>(); 

     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<int> xAxisValues; 
    private readonly IList<int> yAxisValues; 
    private int count; 
    private int xAxisValuesSum; 
    private int xxSum; 
    private int xySum; 
    private int yAxisValuesSum; 

    public Trendline(IList<int> yAxisValues, IList<int> 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; 
    } 
} 
+2

Considere la solución propuesta por Bedwyr Humphreys – TecHunter

+0

Creo que esto es asumiendo que los datos están ordenados (debido al uso de 'xAxisVales.First()' y '.Last()') – Thymine

0

gracias tanto para la solución, que estaba rascándome la cabeza.
Así es como apliqué la solución en Excel.
Utilicé con éxito las dos funciones dadas por MUHD en Excel:
a = (suma (x * y) - suma (x) suma (y)/n)/(suma (x^2) - suma (x)^2/n)
b = suma (y)/n - b (suma (x)/n)
(cuidado mi a y b son el by a en la solución de MUHD).

- Hecho 4 columnas, por ejemplo:
NB: mis valores de valores están en B3: B17, entonces tengo n = 15;
mis valores x son 1,2,3,4 ... 15.
1. Columna B: conocidas de x
2. Columna C: de Y Conocido
3. Columna D: La línea de tendencia computarizada
4. Columna E: valores de b * valores de C (E3 = B3 * C3, E4 = B4 * C4, ..., E17 = B17 * C17)
5. Columna F: x valores al cuadrado
A continuación, sumar las columnas B, C y E, las sumas van en la línea 18 para mí, así que tengo B18 como suma de Xs, C18 como suma de Ys, E18 como suma de X * Y y F18 como suma de cuadrados.
para calcular una, introducir la fórmula followin en cualquier célula (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 columna D, el cálculo de la línea de tendencia de acuerdo con la 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.

14

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

Slope es b, Intercept es a

public class Trendline 
{ 
    public Trendline(IList<decimal> yAxisValues, IList<decimal> xAxisValues) 
     : this(yAxisValues.Select((t, i) => new Tuple<decimal, decimal>(xAxisValues[i], t))) 
    { } 
    public Trendline(IEnumerable<Tuple<Decimal, Decimal>> 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; 
    } 
} 
0

Ésta es la forma en que calcula la pendiente: Fuente: http://classroom.synonym.com/calculate-trendline-2709.html

class Program 
    { 
     public double CalculateTrendlineSlope(List<Point> 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; 
    } 
Cuestiones relacionadas