Frage

Google ist nicht mein Freund – es ist lange her, dass ich an der Uni Statistikunterricht hatte … Ich muss die Start- und Endpunkte für eine Trendlinie in einem Diagramm berechnen – gibt es eine einfache Möglichkeit, das zu tun?(Arbeiten in C#, aber welche Sprache auch immer für Sie geeignet ist)

War es hilfreich?

Lösung

Vorausgesetzt, die Trendlinie ist gerade, ermitteln Sie die Steigung, indem Sie zwei beliebige Punkte auswählen und Folgendes berechnen:

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

Dann müssen Sie den Versatz für die Linie ermitteln.Die Linie wird durch die Gleichung angegeben:

(B) y = Offset + Steigung*x

Sie müssen also nach dem Offset auflösen.Wählen Sie einen beliebigen Punkt auf der Linie und berechnen Sie den Versatz:

(C) Offset = y - (Steigung*x)

Jetzt können Sie Steigung und Versatz in die Liniengleichung (B) einfügen und erhalten die Gleichung, die Ihre Linie definiert.Wenn Ihre Leitung Rauschen aufweist, müssen Sie sich für einen Mittelungsalgorithmus entscheiden oder eine Art Kurvenanpassung verwenden.

Wenn Ihre Linie nicht gerade ist, müssen Sie nachsehen Kurvenanpassung, oder Anpassung der kleinsten Quadrate - nicht trivial, aber machbar.Sie sehen die verschiedenen Arten der Kurvenanpassung unten auf der Webseite zur Anpassung der kleinsten Quadrate (exponentiell, polynomisch usw.), wenn Sie wissen, welche Art von Anpassung Sie möchten.

Wenn es sich hierbei um einen Einzelfall handelt, verwenden Sie außerdem Excel.

Andere Tipps

Vielen Dank an alle für Ihre Hilfe. Ich war ein paar Tage lang von diesem Thema verschont und bin gerade darauf zurückgekommen. Ich konnte das zusammenbasteln. Nicht der eleganteste Code, aber er funktioniert für meine Zwecke. Ich dachte, ich würde es teilen, wenn Jemand anderes stößt auf dieses Problem:

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;
    }
}

OK, hier ist meine beste Pseudo-Mathe:

Die Gleichung für Ihre Linie lautet:

Y = a + bX

Wo:

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

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

Wobei sum(xy) die Summe aller x*y usw. ist.Ich gebe zu, dass es nicht besonders klar ist, aber es ist das Beste, was ich ohne Sigma-Symbol machen kann :)

...und jetzt mit zusätzlichem Sigma

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

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

Wobei Σ(xy) die Summe aller x*y usw. ist.und n ist die Anzahl der Punkte

Hier ist eine sehr schnelle (und halb schmutzige) Implementierung von Die Antwort von Bedwyr Humphreys.Die Schnittstelle sollte kompatibel sein mit @mattist auch die Antwort, verwendet aber decimal anstatt int und verwendet mehr IEnumerable-Konzepte, um es hoffentlich einfacher zu verwenden und zu lesen.

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;
    }
}

Bezüglich einer früheren Antwort

Wenn (B) y = Offset + Steigung*x

Dann (C) Offset = y/(Steigung*x) ist falsch

(C) sollte sein:

Offset = y-(Steigung*x)

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

Wenn Sie Zugriff auf Excel haben, schauen Sie in der Hilfe im Abschnitt „Statistische Funktionen“ der Funktionsreferenz nach.Für die beste geradlinige Anpassung benötigen Sie SLOPE und INTERCEPT und die Gleichungen sind genau dort.

Oh, Moment, sie sind auch hier online definiert: http://office.microsoft.com/en-us/excel/HP052092641033.aspx für SLOPE, und es gibt einen Link zu INTERCEPT.Dies setzt natürlich voraus, dass MS die Seite nicht verschiebt. Versuchen Sie in diesem Fall, nach etwas wie „STEIGUNGSABSCHNITTGLEICHUNG Excel-Site:microsoft.com“ zu googeln – der angegebene Link stellte sich gerade als dritter heraus.

So habe ich die Steigung 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;
    }

Hier ist, was ich letztendlich verwendet habe.

public class DataPoint<T1,T2>
{
    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<DataPoint<long, decimal>> 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;
    }
}

Mein Datensatz verwendet einen Unix-Zeitstempel für die x-Achse und eine Dezimalzahl für die y-Achse.Ändern Sie diese Datentypen entsprechend Ihren Anforderungen.Für die bestmögliche Leistung führe ich alle Summenberechnungen in einer Iteration durch.

Vielen Dank für die Lösung, ich habe mir den Kopf zerbrochen.
So habe ich die Lösung in Excel angewendet.
Ich habe die beiden von MUHD bereitgestellten Funktionen in Excel erfolgreich 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 das b und a in der Lösung von MUHD).

- 4 Spalten erstellt, zum Beispiel:
Hinweis: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:Bekannte x
2.Spalte C:Bekannte Y's
3.Spalte D:Die berechnete Trendlinie
4.Spalte E:B-Werte * C-Werte (E3=B3*C3, E4=B4*C4, ..., E17=B17*C17)
5.Spalte F:x-Quadrat-Werte
Ich summiere dann die Spalten B, C und E, die Summen kommen für mich in Zeile 18, also habe ich B18 als Summe von Xs, C18 als Summe von Ys, E18 als Summe von X*Y und F18 als Summe der Quadrate.
Um a zu berechnen, geben Sie die folgende Formel in eine beliebige Zelle ein (bei mir F35):
F35=(E18-(B18*C18)/15)/(F18-(B18*B18)/15)
Um b zu berechnen (in F36 für mich):
F36=C18/15-F35*(B18/15)
Spalte D-Werte, Berechnung der Trendlinie gemäß y = ax + b:
D3=$F$35*B3+$F$36, D4=$F$35*B4+$F$36 und so weiter (bis D17 für mich).

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

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top