Comment calculer une ligne de tendance pour un graphique?

Google n'est pas mon ami - Cela fait longtemps que ma classe de statistiques au collège...J'ai besoin de calculer les points de début et fin pour la courbe de tendance sur un graphique - est-il un moyen facile de faire cela? (travailler en C # mais quelle que soit la langue qui fonctionne pour vous)

46
demandé sur Steven V 2008-09-04 09:41:07

9 réponses

Étant donné que la ligne de tendance est droite, trouvez la pente en choisissant deux points et en calculant:

(a) Pente = (y1-y2) / (x1-x2)

Ensuite, vous devez trouver le décalage pour la ligne. La ligne est spécifiée par l'équation:

(B) y = décalage + Pente * x

Vous devez donc résoudre pour offset. Choisissez n'importe quel point sur la ligne, et résolvez pour le décalage:

(C) décalage = y- (Pente * x)

Maintenant, vous pouvez brancher la pente et le décalage dans l'équation de ligne (B) et avoir le équation qui définit votre ligne. Si votre ligne a du bruit, vous devrez décider d'un algorithme de moyenne, ou utiliser un ajustement de courbe de quelque sorte.

Si votre ligne n'est pas droite, vous devrez regarder dans ajustement de la courbe, ou ajustement des moindres carrés - non trivial, mais faisable. Vous verrez les différents types d'ajustement de courbe au bas de la page Web d'ajustement des moindres carrés (exponentiel, polynôme, etc.) si vous savez quel type d'ajustement vous souhaitez.

Aussi, si cela est un one-off, utilisez Excel.

15
répondu Adam Davis 2018-04-19 15:09:01

Merci à tous pour votre aide-j'étais hors de ce problème pendant quelques jours et je suis juste revenu dessus-a pu bricoler cela ensemble - pas le code le plus élégant, mais cela fonctionne pour mes besoins-pensé que je partagerais si quelqu'un d'autre rencontre ce problème:

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;
    }
}
33
répondu matt 2008-09-06 06:39:15

OK, voici mon meilleur pseudo-mathématiques:

L'équation pour votre ligne est:

Y = a + bX

Où:

B = (sum(x*y) - sum(x)sum(y)/n) / (sum(x^2) - somme(x)^2/n)

A = Somme (y) / n-b(somme (x)/n)

Où sum (xy) est la somme de tous les x*y etc. Pas particulièrement clair, je concède, mais c'est le mieux que je puisse faire sans un symbole sigma:)

... et maintenant avec Sigma ajouté

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

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

Où Σ (xy) est la somme de tous les x*y etc. et n est le nombre de points

26
répondu blank 2015-01-19 08:17:24

Voici une implémentation très rapide (et semi-sale) de la réponse de Bedwyr Humphreys . L'interface devrait être compatible avec la réponse de @matt, mais utilise decimal au lieu de int et utilise plus de concepts IEnumerable pour le rendre plus facile à utiliser et à lire.

Slope est b, Intercept est 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;
    }
}
15
répondu Thymine 2017-05-23 12:17:51

Concernant une réponse précédente

Si (B) y = décalage + Pente * x

, Puis (C) offset = y/(pente*x) est faux

C) devrait être:

décalage = y-(Pente * x)

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

3
répondu 2009-04-03 09:48:29

Si vous avez accès à Excel, regardez dans la section" Fonctions statistiques " de la référence de la fonction dans L'aide. Pour le meilleur ajustement en ligne droite, vous avez besoin de pente et D'interception et les équations sont là.

Oh, attendez, ils sont également définis en ligne ici: http://office.microsoft.com/en-us/excel/HP052092641033.aspx pour la pente, et il y a un lien pour intercepter. Bien sûr, cela suppose que MS ne déplace pas la page, auquel cas essayez de googler pour quelque chose comme " slope INTERCEPT Équation Excel site:microsoft.com " - le lien donné avéré troisième tout à l'heure.

1
répondu Mike Woodhouse 2008-09-04 08:24:10

Voici ce que j'ai fini par utiliser.

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

Mon ensemble de données utilise un horodatage Unix pour l'axe x et une décimale pour le y. changez ces types de données pour répondre à vos besoins. Je fais tous les calculs de Somme en une seule itération pour la meilleure performance possible.

1
répondu Todd Skelton 2018-07-02 16:31:07

Merci beaucoup pour la solution, je me grattais la tête.
Voici comment j'ai appliqué la solution dans Excel.
J'ai utilisé avec succès les deux fonctions Données par MUHD dans Excel:
a = (sum(x*y) - sum(x)sum(y)/n) / (sum(x^2) - somme(x)^2/n)
b = somme (y) / n-B(somme (x)/n)
(attention, mes a et b sont les B et a dans la solution de MUHD).

- Fait 4 colonnes, par exemple:
NB: mes valeurs y sont dans B3: B17, donc j'ai n = 15;
mes valeurs x sont 1,2,3,4...15.
1. Colonne B: X connus
2. Colonne C: Y connus
3. Colonne D: la ligne de tendance calculée
4. Colonne E: valeurs B * valeurs C (E3 = B3 * C3, E4=B4 * C4, ..., E17 = B17 * C17)
5. Colonne F: X valeurs au carré
Je additionne ensuite les colonnes B, C et E, les sommes vont à la ligne 18 pour moi, donc J'ai B18 comme somme de Xs, C18 comme somme de Ys, E18 comme somme de X*Y, et F18 comme somme de carrés.
Pour calculer a, entrez la formule suivante dans n'importe quelle cellule (F35 pour moi):
F35=(E18-(B18*C18)/15)/(F18-(B18*B18)/15)
De calculer b (en F36 pour moi):
F36 = C18 / 15-F35*(B18/15)
Valeurs de la colonne D, calculant la ligne de tendance selon y = ax + b:
D3= $ F $ 35 * B3 + $ F $ 36, D4= $ F $ 35 * B4 + $ F $ 36 et ainsi de suite (Jusqu'à ce que D17 pour moi).

Sélectionnez les données de colonne (C2: D17) pour créer le graphique.
HTH.

0
répondu franchsesko 2013-01-09 13:06:45

C'est la façon dont j'ai calculé la pente: Source: 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;
    }
0
répondu Magn3144 2018-01-07 09:51:58