Аппроксимация на php

217
09 мая 2018, 02:44

Нужно разобраться с аппроксимацией. Есть массив, допустим формата (формат может быть любой, это для примера)

[1517443199] => 10285.10000000
[1517702399] => 9199.96000000
[1517961599] => 7652.14000000
[1518220799] => 8683.92000000
[1518479999] => 8903.00000000
[1518739199] => 10000.09000000
[1518998399] => 10383.43000000
[1519257599] => 10437.60000000
[1519516799] => 9694.51000000
[1519775999] => 10569.04000000
[1520035199] => 11039.00000000
[1520294399] => 11454.00000000
[1520553599] => 9271.64000000
[1520812799] => 9533.57000000
[1521071999] => 8170.00000000
[1521331199] => 7824.80000000
[1521590399] => 8909.98000000
[1521849599] => 8898.03000000
[1522108799] => 8134.23000000
[1522367999] => 7090.14000000
[1522627199] => 6813.01000000
[1522886399] => 6796.10000000
[1523145599] => 6895.80000000
[1523404799] => 6843.90000000
[1523663999] => 7877.41000000
[1523923199] => 8064.92000000
[1524182399] => 8278.00000000
[1524441599] => 8787.02000000
[1524700799] => 8869.99000000
[1524959999] => 9348.00000000
[1525219199] => 9071.48000000
[1525478399] => 9713.99000000
[1525737599] => 9429.02000000

где ключ – координаты по оси oX, значение – координаты по оси oY.

Цель – аппроксимировать данные так чтобы график вышел максимально сглаженным (на самом деле количество данных в массиве на много-много больше). Для этого, как вы понимаете, на самом деле нужна интерполяция, но я решил посмотреть на результаты аппроксимации моего графика.

Нашёл метод для кусочно-линейной апроксимации на с++. Быстрым движением руки преобразил его под php.

function approximat($X, $Y, $x)
{
// вычисление ближайшего большего и его индекса
    $n = count($Y);
    $max = $X[0];
    $indexMax = 0;  // индекс
    for ($i = 0; $i < $n; $i++) {
        if ($X[$i] <= $max && $x <= $X[$i]) {
            $max = $X[$i];
            $indexMax = $i;
        }
    }
// вычисление ближайшего меньшего и его индекса
    $min = $X[$n];
    $indexMin = 0;
    for ($i = 0; $i < $n; $i++) {
        if ($X[$i] >= $min && $x >= $X[$i]) {
            $min = $X[$i];
            $indexMin = $i;
        };
    }
    // вычисление нужного Y
        $Y = (($max - $x) / ($max - $min)) * $Y[$indexMin] + (($x - $min) / ($max - $min)) * $Y[$indexMax];
    return $Y;
}

Как применить пока не разобрался, нам нужно ведь по факту получить новый массив, как с точками в промежуточных значениях, так и с новыми значения в существующих.

Главный вопрос – помогите пожалуйста разобраться с самим алгоритмом аппроксимации.

for ($i = $data_x[0]; $i < $data_x[count($data_x) - 1]; $i = $i + 100) {
    $data_nx[] = $i;
}
$inter = [];
foreach ($data_nx as $x) {
    $inter[$x] = approximat($data_x, $data_y, $x);
}

data_nx - новые x-ы data_y и data_x массивы координат. Предполагаю что моя функция работает не совсем верно.(Исходя из провала в начале графика). Но в общем ок.

Answer 1

Давайте разбираться:

$X - это массив с oX;

$Y - это массив с oY;

$x - это новое значение oX, для которого хотим получить oY.

Значит, если у ваш массив называется $ARRAY, то мы знаем как запихнуть туда первые 2 значения:

$X = array_keys($ARRAY);

$Y = array_values($ARRAY);

Третий параметр - новое значение.

Исходя из этого, например, у вас есть массив $ARRAY с значениями, и нужно еще получить значения для массива $NEW, с координатами по oX: 1, 2 и 3. Собсна:

$ARRAY = array(...);            //  Ваш массив
$X = array_values($ARRAY);   // Пихаем ключи (наши oX)
$Y = array_keys($ARRAY);         // Пихаем значения (наши oY)
$NEW = array(1,2,3);            //  Массив с oX, для которых надо найти oY
$RESULT = array();              //  Новый массив, где ключ будет oX, а значение oY
foreach ($NEW as $NEW_X)
{
    $RESULT[$NEW_X] = approximat($X, $Y, $NEW_X);
}

Теперь чтобы построить график у вас есть ваши точки в $ARRAY, и те которые были неизвестны (а было известно только oX) в $RESULT, а там разберетесь.

P.S. Это ни в коем случае не оптимальный пример, но оптимизацией займетесь сами.

READ ALSO
Восстановление пароля удаленно через ldap

Восстановление пароля удаленно через ldap

Недавно пришлось на проекте сделать авторизацию через удаленный ldap серверСкажите, есть ли возможность в этом случае сделать функционал...

196
Вывод информации о товаре в списке заказов Опенкарт

Вывод информации о товаре в списке заказов Опенкарт

Подскажите, как мне вывести данные о заказанном товаре в списке заказов в профиле опенкарт 2, например, фото, описание и название? Возможно,...

157
Не пойму как отрабатывает скрипт

Не пойму как отрабатывает скрипт

Вот скрипт, выводит на странице три отзыва посетителей случайным образом(и рисует оценку звездочками)Файлик текстовый, формата: х|х|х|х|

202
localStorage.setitem и метод filter()

localStorage.setitem и метод filter()

У меня есть 2 ссылки и 2 блока

176