2008-09-04 9 views
42

Google ist nicht mein Freund - es ist lange her, seit ich meinen Statistik-Kurs auf dem College habe ... Ich muss Start- und Endpunkte für eine Trendlinie in einem Diagramm berechnen - gibt es einen einfachen Weg dazu? (Arbeits in C#, aber was auch immer die Sprache für Sie arbeitet)Wie berechne ich eine Trendlinie für ein Diagramm?

Antwort

14

Da die Trendlinie gerade ist, die Steigung zu finden, indem zwei beliebige Punkte der Auswahl und Berechnung:

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

Dann müssen Sie den Offset für die Linie finden. Die Linie wird durch die folgende Gleichung angegeben:

(B) y = Offset + x * Steigung

Sie müssen also für den Offset lösen. Pick jeden Punkt auf der Linie, und löse für den Offset:

(C) offset = y/(Steigung * x)

Jetzt können Sie stecken Steigung und Offset in die Geradengleichung (B) und haben die Gleichung Das definiert deine Linie. Wenn Ihre Linie Rauschen aufweist, müssen Sie sich für einen Mittelungsalgorithmus entscheiden oder eine Kurvenanpassung verwenden. Wenn Ihre Linie nicht gerade ist, müssen Sie in Curve fitting oder Least Squares Fitting suchen - nicht trivial, aber machbar. Sie werden die verschiedenen Arten der Kurvenanpassung unten auf der Seite der kleinsten Quadrate (exponentiell, Polynom usw.) sehen, wenn Sie wissen, welche Art von Anpassung Sie möchten.

Verwenden Sie auch Excel, wenn dies eine einmalige ist.

-Adam

+28

Ich bin mir ziemlich sicher, dass dies keine angepasste Trendlinie ergeben wird; Die in (A) berechnete Steigung wird sich signifikant unterscheiden, je nachdem, welche "zwei Punkte" Sie wählen. Dies ist keine angepasste Trendlinie. –

+2

[Ich bevorzuge diese, die ich gefunden habe] (http://math.stackexchange.com/questions/204020/what-is-the-equation-used-to-calculate-a-linear-trendline/204021#204021) – TecHunter

+1

@Jay So der Satz: "Wenn Ihre Zeile Rauschen hat, müssen Sie sich für einen Mittelungsalgorithmus entscheiden oder eine Kurvenanpassung verwenden." –

25

OK, hier ist meine beste Pseudo-Mathematik:

Die Gleichung für die Linie ist:

Y = a + bX

Wo:

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

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

Wo Summe (xy) ist die Summe aller x * y usw. nicht besonders klar ich zugeben, aber es ist das Beste, was ich ohne Sigma-Symbol tun kann :)

... und jetzt mit zusätzlichem Sigma

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

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

Wo Σ (xy) ist die Summe aller x * y etc., und n ist die Anzahl der Punkte

+0

dies eine große Hilfe sein würde, wenn ich herausfinden kann, was n repräsentiert. – Praesagus

+0

Mathe Klasse kommt zurück - n ist die Anzahl der Punkte auf einer Achse richtig? – Praesagus

+0

Ja, n ist die Anzahl der Punkte, die Sie haben. – blank

1

Wenn Sie Zugriff auf Excel haben, schauen Sie in der „Statistik-Funktionen“ der Funktionsreferenz innerhalb Hilfe. Für die geradlinige bestmögliche Anpassung benötigen Sie SLOPE und INTERCEPT und die Gleichungen sind genau da.

Oh, Moment mal, sie sind auch online definiert hier: http://office.microsoft.com/en-us/excel/HP052092641033.aspx für SLOPE, und es gibt einen Link zu INTERCEPT. Natürlich geht das davon aus, dass MS die Seite nicht verschiebt. In diesem Fall versuchen Sie Google für etwas wie "SLOPE INTERCEPT EQUATION Excel-Website: microsoft.com" - der angegebene Link ist gerade erst dritte geworden.

31

Vielen Dank an alle für Ihre Hilfe - ich war aus diesem Problem für ein paar Tage und kam gerade zurück - konnte zusammen dies zusammen - nicht die eleganteste Code, aber es funktioniert für meine Zwecke - dachte ich ‚d Anteil, wenn jemand dieses Problem begegnet:

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

Betrachten Sie die von Bedwyr Humphreys vorgeschlagene Lösung – TecHunter

+0

Ich glaube, das geht davon aus, dass die Daten sortiert sind (aufgrund der Verwendung von 'xAxisVales.First()' und '.Last()') – Thymine

0

Vielen Dank für die Lösung, ich war kratze mich am Kopf.
So habe ich die Lösung in Excel angewendet.
Ich habe erfolgreich die beiden Funktionen von MUHD in Excel verwendet:
a = (Summe (x * y) - Summe (x) Summe (y)/n)/(Summe (x^2) - Summe (x)^2/n)
b = Summe (y)/n - b (Summe (x)/n)
(Vorsicht mein a und b sind die b und a in MUHD-Lösung).

- 4 Spalten gemacht, zum Beispiel:
NB: meine Werte y Werte sind in B3: B17, also habe ich n = 15;
meine x Werte sind 1,2,3,4 ... 15.
1. Spalte B: Bezeichnen der x
2. Spalte C: Bezeichnen der y
3. Spalte D: Die berechneten Trendlinie
4. Spalte E: B-Werte * C-Werte (E3 = B3 * C3, E4 = B4 * C4, ..., E17 = B17 * C17)
5. Spalte F: x Quadratwerte
Ich summiere dann die Spalten B, C und E, die Summen gehen in Zeile 18 für mich, also habe ich B18 als Summe von Xs, C18 als Summe von Ys, E18 als Summe von X * Y und F18 als Quadratsumme.
A, geben Sie die followin Formel in einer beliebigen Zelle (F35 für mich) zu berechnen:
F35 = (E18- (B18 * C 18)/15)/(F18- (B18 * B18)/15)
zu berechnen b (in F36 für mich):
F36 = C18/15-F35 * (B18/15)
Spalte D-Werte, die Berechnung der Trendlinie gemäß der y = ax + b:
D3 = $ F $ 35 * B3 + $ F $ 36, D4 = $ F $ 35 * B4 + $ F $ 36 usw. (bis D17 für mich).

Wählen Sie die Spaltendaten (C2: D17), um das Diagramm zu erstellen.
HTH.

14

Hier ist eine sehr schnelle (und semi-dreckige) Implementierung von Bedwyr Humphreys's answer.Die Schnittstelle sollte auch mit der @matt Antwort kompatibel sein, verwendet aber decimal statt int und verwendet mehr IEnumerable-Konzepte, um die Verwendung und das Lesen zu erleichtern.

Slope ist b, Intercept ist 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

Dies ist die Art, wie ich die Neigung berechnet: Quelle: 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; 
    }