Подтвердить что ты не робот

Как рассчитать линию тренда для графика?

Google не является моим другом - это было давно, так как мой класс статистики в колледже... Мне нужно рассчитать начальную и конечную точки для линии тренда на графике - есть ли простой способ сделать это? (работает на С#, но на любом языке работает для вас)

4b9b3361

Ответ 1

Учитывая, что линия тренда прямая, найдите наклон, выбирая любые две точки и вычисляя:

(A) наклон = (y1-y2)/(x1-x2)

Затем вам нужно найти смещение для строки. Линия задается уравнением:

(B) y = смещение + наклон * x

Итак, вам нужно решить для смещения. Выберите любую точку на линии и решите для смещения:

(C) offset = y/(наклон * x)

Теперь вы можете подключить наклон и смещение в линейном уравнении (B) и иметь уравнение, определяющее вашу линию. Если ваша линия имеет шум, вам придется решать алгоритм усреднения или использовать какой-либо подход.

Если ваша строка не является прямой, вам нужно будет изучить Curve fitting или Фиксация наименьших квадратов - нетривиальная, но умелая. Вы увидите различные типы фитингов в нижней части веб-страницы с наименьшими квадратами (экспоненциальные, полиномиальные и т.д.), Если вы знаете, какую форму вы хотите.

Кроме того, если это одноразовый, используйте Excel.

-Adam

Ответ 2

Спасибо всем за вашу помощь. Я пару дней пробовал эту проблему и только что вернулся к ней - смог согнуть это вместе - не самый элегантный код, но он работает для моих целей - думал, d, если кто-то еще сталкивается с этой проблемой:

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

Ответ 3

ОК, вот моя лучшая псевдоматра:

Уравнение для вашей линии:

Y = a + bX

Где:

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

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

Где сумма (xy) является суммой всех x * y и т.д. Не особо я понимаю, что я согласен, но это лучшее, что я могу сделать без символа сигмы:)

... и теперь с добавлением Sigma

b = (& Sigma; (xy) - (& Sigma; x & Sigma; y)/n)/(& Sigma; (x ^ 2) - (& Sigma; x) ^ 2/n)

a = (& Sigma; y)/n - b ((& Sigma; x)/n)

Где & Sigma; (xy) - сумма всех x * y и т.д., а n - число точек

Ответ 4

Вот очень быстрая (и полу-грязная) реализация ответа Бедвира Хамфриса. Интерфейс должен быть совместим с ответом @matt, но использует decimal вместо int и использует больше концепций IEnumerable, чтобы, надеюсь, упростить их использование и прочитать.

Slope is b, Intercept is 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;
    }
}

Ответ 5

Относительно предыдущего ответа

if (B) y = смещение + наклон * x

тогда (C) offset = y/(наклон * x) неверен

(C) должно быть:

offset = y- (наклон * x)

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

Ответ 6

Если у вас есть доступ к Excel, просмотрите раздел "Статистические функции" справочника функций в Справке. Для прямой линии наилучшего соответствия вам нужны SLOPE и INTERCEPT, и уравнения находятся прямо там.

О, держитесь, они также определены здесь: http://office.microsoft.com/en-us/excel/HP052092641033.aspx для SLOPE, и есть ссылка на INTERCEPT. Конечно, предполагается, что MS не перемещает страницу, и в этом случае попробуйте Googling для чего-то вроде "SLAPE INTERCEPT EQUATION Excel site: microsoft.com" - ссылка, показанная сейчас третьей.

Ответ 7

Большое спасибо за решение, я царапаю себе голову.
Вот как я применил решение в Excel.
Я успешно использовал две функции, заданные MUHD в Excel:
a (сумма (x * y) - сумма (x) sum (y)/n)/(сумма (x ^ 2) - сумма (x) ^ 2/n)
b = sum (y)/n - b (sum (x)/n)
(осторожны мои a и b - это b и a в решении MUHD).

- Сделано 4 столбца, например:
NB: значения моих значений y находятся в B3: B17, поэтому я n = 15;
    мои значения x составляют 1,2,3,4... 15.
1. Столбец B: Известный x's 2. Столбец C: Известный y's 3. Столбец D: Вычисленная линия тренда
4. Значения столбцов E: B * C (E3 = B3 * C3, E4 = B4 * C4,..., E17 = B17 * C17)
5. Столбец F: значения квадрата x
Затем я суммирую столбцы B, C и E, суммы идут в строке 18 для меня, поэтому я имею B18 как сумму Xs, C18 как сумму Ys, E18 как сумму X * Y и F18 как сумму квадратов.
Чтобы вычислить a, введите следующую формулу в любой ячейке (F35 для меня):
F35 = (E18- (В18 * С18)/15)/(F18- (В18 * В18)/15)
Чтобы вычислить b (в F36 для меня):
F36 = С18/15-F35 * (В18/15)
Значения столбца D, вычисляя линию тренда в соответствии с y = ax + b:
D3 = $F $35 * B3 + $F $36, D4 = $F $35 * B4 + $F $36 и т.д. (До D17 для меня).

Выберите столбцы (C2: D17), чтобы сделать график.
НТН.