Как предсказать следующее следующее число в последовательности в R

Я хочу создать функцию для предсказания следующего числа в последовательности геометрических последовательностей, таких как эти или любые другие кратные n:

1 2 4 8 16 32 64
2 4 8 16 32 64 128
3 6 12 24 48 96 192

1 3 9 27 81 243 729
2 6 18 54 162 486 1458
3 9 27 81 243 729 2187

Я пробовал использовать этот метод (Как получить следующий номер в последовательность в R), однако кажется, что она работает только с линейными последовательностями. Кроме того, как можно реализовать оператор IF, чтобы проверить, является ли последовательность геометрической последовательностью, а не каким-либо другим типом последовательности, например, линейной?


person Bethan Huish    schedule 25.08.2019    source источник


Ответы (2)


Для геометрического ряда отношение последовательных значений является постоянным, поэтому умножение этого отношения на текущее значение дает следующее значение.

Чтобы проверить, является ли ряд геометрическим, мы можем взять отношение каждой последующей пары значений в ряду, и если все эти отношения равны, ряд является геометрическим. Поскольку это эквивалентно проверке, равна ли их дисперсия нулю, мы можем легко сделать это, используя var. Поскольку арифметика с плавающей запятой не является точной, мы проверяем, меньше ли дисперсия eps .

Обратите внимание, что is.geo возвращает NA для серии длиной 1 или 2, а nextValue возвращает NA, если is.geo не возвращает TRUE.

nextValue <- function(x) {
  if (!isTRUE(is.geo(x))) NA
  else {
    y <- tail(x, 2)
    y[2]^2 / y[1]
  }
}

is.geo <- function(x, eps = 1e-5) var(x[-1] / x[-length(x)]) < eps

Тест

Используя m, определенный в примечании в конце, мы можем добавить к нему следующее значение как новый столбец:

cbind(m, apply(m, 1, nextValue))

давая:

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,]    1    2    4    8   16   32   64  128
[2,]    2    4    8   16   32   64  128  256
[3,]    3    6   12   24   48   96  192  384
[4,]    1    3    9   27   81  243  729 2187
[5,]    2    6   18   54  162  486 1458 4374
[6,]    3    9   27   81  243  729 2187 6561

Также мы можем протестировать каждую строку m, чтобы проверить, является ли она геометрической:

apply(m, 1, is.geo)
## [1] TRUE TRUE TRUE TRUE TRUE TRUE

is.geo(c(1, 2, 4, 12))
## [1] FALSE

Использование лм

Если метод ссылки, показанный в вопросе, означает использование lm, тогда мы можем использовать lm, если ряд строго положителен, отметив, что log такого геометрического ряда является арифметическим, поэтому мы можем подогнать журнал ряда к 1, 2, 3, ... . Если остатки равны нулю, что происходит, когда отклонение равно нулю, то это удовлетворяет этому требованию.

fit <- function(x) {
    ix <- seq_along(x)
    lm(log(x) ~ ix)
}

nextValue2 <- function(x) {
  if (!isTRUE(is.geo2(x))) NA
  else exp( predict(fit(x), list(ix = length(x) + 1)) )
}

is.geo2 <- function(x, eps = 1.e-5) {
  if (length(x) <= 2) NA
  else deviance(fit(x)) < eps
}

Примечание

m <- matrix(c(1L, 2L, 3L, 1L, 2L, 3L, 2L, 4L, 6L, 3L, 6L, 9L, 4L, 
8L, 12L, 9L, 18L, 27L, 8L, 16L, 24L, 27L, 54L, 81L, 16L, 32L, 
48L, 81L, 162L, 243L, 32L, 64L, 96L, 243L, 486L, 729L, 64L, 128L, 
192L, 729L, 1458L, 2187L), 6)
person G. Grothendieck    schedule 25.08.2019
comment
Просто из любопытства, !isTRUE отличается от isFALSE? - person NelsonGon; 25.08.2019
comment
Они различны, если аргумент NA. !isTRUE(NA) ИСТИНА, а isFALSE(NA) ЛОЖЬ. - person G. Grothendieck; 25.08.2019
comment
@ Г. Гротендик, можем ли мы сделать то же самое для обратной геометрической серии, например. (256 128 64 32 16)? - person Bethan Huish; 26.08.2019
comment
Это все еще геометрия - person G. Grothendieck; 26.08.2019
comment
@ГРАММ. Grothendieck, поэтому у меня наконец-то появилась возможность протестировать ваше решение. При запуске функции is.geo для такой последовательности, как (90,93,96,99,102,105), она возвращает TRUE, несмотря на то, что это линейная последовательность - person Bethan Huish; 26.08.2019
comment
используйте меньшее значение для eps, например. is.geo(x, eps = 1e-10) - person G. Grothendieck; 27.08.2019

Если это просто геометрическая последовательность, вы можете найти множитель как factor <- seq[2]/seq[1]. Если не знать тип последовательности, найти формулу в общем случае невозможно.

Однако вы знаете общую формулу последовательности, поэтому у вас есть некоторые переменные, которые можно вычислить с помощью некоторых членов последовательности. Например, для геометрической последовательности мы знаем, что a_n = factor * a_{n-1}. Следовательно, заменяя некоторые члены последовательности, мы можем найти здесь множитель. Это уравнение с одной переменной. Можно сказать, что factor = a_n / a_{n-1}.

В качестве другого примера предположим, что мы знаем, что формула последовательности похожа на a_n = alpha * a_{n-1} + beta * a_{n-2}. Теперь мы можем найти alpha и beta, используя четыре члена последовательности (a_1, a_2, a_3 и `a_4).

В последнем случае у вас может быть общая форма последовательности без какой-либо переменной, такой как a_n = a_{n-1} + n. Если у вас есть это, вы можете легко предсказать последний член на основе требуемых последних членов последовательности.

person OmG    schedule 25.08.2019
comment
Большое спасибо, в таком случае я думаю, что-то простое, как geoSolve ‹- function(){ factor ‹- seq[2]/seq[1]; хвост (последовательность, n = 1) * фактор; } может предоставить решение, верно? - person Bethan Huish; 25.08.2019
comment
@BethanHuish да, вроде. вам нужно добавить последний результат во фрейм данных, чтобы getNext работал правильно. - person OmG; 25.08.2019
comment
извините, я не совсем уверен, что понимаю, что вы имеете в виду, я запустил этот код, и, похоже, он работает нормально. Есть ли что-то, что мне не хватает? - person Bethan Huish; 25.08.2019
comment
@BethanHuish Да. Это правильно. Однако вам нужно добавить последний результат в последовательность, чтобы получить правильный следующий прогноз. - person OmG; 25.08.2019
comment
а ок я понимаю - person Bethan Huish; 26.08.2019