Google не является моим другом - это было давно, так как мой класс статистики в колледже... Мне нужно рассчитать начальную и конечную точки для линии тренда на графике - есть ли простой способ сделать это? (работает на С#, но на любом языке работает для вас)
Как рассчитать линию тренда для графика?
Ответ 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)
Ответ 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), чтобы сделать график.
НТН.