Поэтому я прочитал два связанных вопроса для расчета линии тренда для графика, но я все еще потерян.
У меня есть массив координат xy, и я хочу придумать еще один массив координат xy (может быть меньше координат), которые представляют собой логарифмическую линию тренда с использованием PHP.
Я передаю эти массивы в javascript для построения графиков на стороне клиента.
Поскольку мы можем преобразовать логарифмическую функцию в прямую, взяв log
значений x
, мы можем выполнить линейную аппроксимацию кривой наименьших квадратов . Фактически, работа была выполнена для нас, и решение представлено в Math World .
Короче говоря, нам присваиваются значения $X
и $Y
из распределения, такие как y = a + b * log(x)
. Метод наименьших квадратов даст некоторые значения aFit
и bFit
которые минимизируют расстояние от параметрической кривой до заданных точек данных.
Вот пример реализации в PHP:
Сначала я создам некоторые случайные данные с известным базовым распределением, заданным $a
и $b
// True parameter valaues $a = 10; $b = 5; // Range of x values to generate $x_min = 1; $x_max = 10; $nPoints = 50; // Generate some random points on y = a * log(x) + b $X = array(); $Y = array(); for($p = 0; $p < $nPoints; $p++){ $x = $p / $nPoints * ($x_max - $x_min) + $x_min; $y = $a + $b * log($x); $X[] = $x + rand(0, 200) / ($nPoints * $x_max); $Y[] = $y + rand(0, 200) / ($nPoints * $x_max); }
Теперь, вот как использовать уравнения, заданные для оценки $a
и $b
.
// Now convert to log-scale for X $logX = array_map('log', $X); // Now estimate $a and $b using equations from Math World $n = count($X); $square = create_function('$x', 'return pow($x,2);'); $x_squared = array_sum(array_map($square, $logX)); $xy = array_sum(array_map(create_function('$x,$y', 'return $x*$y;'), $logX, $Y)); $bFit = ($n * $xy - array_sum($Y) * array_sum($logX)) / ($n * $x_squared - pow(array_sum($logX), 2)); $aFit = (array_sum($Y) - $bFit * array_sum($logX)) / $n;
Затем вы можете создавать точки для вашего Javascript так же плотно, как вам нравится:
$Yfit = array(); foreach($X as $x) { $Yfit[] = $aFit + $bFit * log($x); }
В этом случае оценки кода bFit = 5.17
и aFit = 9.7
, что довольно близко только для 50
точек данных.
Для данных примера, приведенных в комментарии ниже, логарифмическая функция не подходит хорошо.
Решение наименьших квадратов y = -514.734835478 + 2180.51562281 * log(x)
которое по существу является линией в этой области.
Я бы рекомендовал использовать библиотеку: http://www.drque.net/Projects/PolynomialRegression/
Доступно Composer: https://packagist.org/packages/dr-que/polynomial-regression .