Использование параметра ширины rollapply в FUN с неожиданным результатом - PullRequest
0 голосов
/ 17 января 2019

Я использовал rollapply для вычисления, которое берет последнее значение в броске и делит его на среднее значение минус единица, которое отлично работает, как вы сами можете попробовать:

set.seed(123)
v <- xts(rnorm(5, 5, 1), Sys.Date()-5:1)
rollapplyr(v, width = 3, function(x) x[3, ] / mean(x) - 1)

                  [,1]
2019-01-12          NA
2019-01-13          NA
2019-01-14  0.24784729
2019-01-15 -0.07241364
2019-01-16 -0.08178780

Затем мне также нужно было запустить функцию с другим параметром, например. width = 4. Конечно, функцию тоже нужно настроить:

rollapplyr(v, width = 4, function(x) x[4, ] / mean(x) - 1)

                  [,1]
2019-01-12          NA
2019-01-13          NA
2019-01-14          NA
2019-01-15 -0.02670674
2019-01-16 -0.04696956

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

rollapplyr(v, width = 4, function(x, width) x[width, ] / mean(x) - 1)

                 [,1]        [,2]        [,3]        [,4]
2019-01-12         NA          NA          NA          NA
2019-01-13         NA          NA          NA          NA
2019-01-14         NA          NA          NA          NA
2019-01-15 -0.1478253 -0.08442393  0.25895593 -0.02670674
2019-01-16 -0.1137588  0.21861923 -0.05789086 -0.04696956

Кто-нибудь поймет, что концептуально не так с использованием параметра ширины в FUN и как можно объяснить вывод? У кого-нибудь есть идеи, как это сделать правильно?

1 Ответ

0 голосов
/ 19 января 2019

Результат, который вы получите, равен результату из этой строки:

rollapplyr(v, width = 4, function(x) x / mean(x) - 1)

Что происходит внутри, когда у вас есть только 1 столбец, так это то, что вы получаете строки кода ниже и некоторые переменные, которые установлены. Результат установки переменных уже сделан в коде. Функция rollapply немного сложнее.

width <- 4
ind <- as.matrix(seq.int(4, 5))
# FUN passed on from rollappy
FUN <- match.fun(function(x, width) x[width, ] / mean(x) - 1)
sapply(ind, function(i) FUN(.subset_xts(v, 
                                        (i - width + 1):i)))

После этих строк кода происходит сборка возвращаемого xts.

Но как только вы начнете отлаживать то, что происходит в части sapply, (отладка FUN) вы увидите, что width не передается из вызова sapply функции (i) и, следовательно, недоступен когда весело. Только в тех случаях, когда ширина определена внутри rollapply, ширина доступна для функции .subset. То же самое происходит, если вы запускаете вышеуказанные строки кода. Это результат среды, в которой была определена переменная ширины и в которой выполняется FUN. Они разные, что приводит к полученным результатам.

Лучший способ продвинуться вперед - это обернуть объект в другую функцию, как вы упоминали в своем комментарии:

function(v,w) {
  rollapplyr(v, 
             width = w, 
             function(x) x[w, ] / mean(x) - 1)
}

Здесь w определяется на более высоком уровне среды и корректно передается при создании FUN внутри rollapply, который затем выполняется в sapply

.

Более подробную информацию об окружающей среде вы можете найти здесь в расширенной книге R.

...