Использование rollapply для вывода в списки списков

Я хотел бы использовать rollapply или rollapplyr, чтобы применить функцию modwt к моим данным временного ряда.

Я знаком с тем, как работает rollapply / r, но мне нужна помощь в настройке вывода, чтобы я мог правильно сохранять свои результаты при использовании rollapply.

Функция modwt в пакете waveslim берет временной ряд и разлагает его на J уровней, для моей конкретной проблемы J = 4, что означает, что у меня будет 4 набора коэффициентов из моего единственного временного ряда, хранящегося в списке из 5. Из этого списка я меня интересуют только d1, d2, d3 и d4.

Вывод функции modwt выглядит следующим образом

    > str(ar1.modwt)
List of 5
 $ d1: num [1:200] -0.223 -0.12 0.438 -0.275 0.21 ...
 $ d2: num [1:200] 0.1848 -0.4699 -1.183 -0.9698 -0.0937 ...
 $ d3: num [1:200] 0.5912 0.6997 0.5416 0.0742 -0.4989 ...
 $ d4: num [1:200] 1.78 1.86 1.85 1.78 1.65 ...
 $ s4: num [1:200] 4.64 4.42 4.19 3.94 3.71 ...
 - attr(*, "class")= chr "modwt"
 - attr(*, "wavelet")= chr "la8"
 - attr(*, "boundary")= chr "periodic"

В приведенном выше примере я применил функцию modwt к полноразмерному временному ряду длиной 200, но я хочу применить ее к небольшому скользящему окну 30 с помощью rollapply.

Я уже пробовал следующее, но на выходе получается большая матрица, и я не могу легко определить, какие значения принадлежат d1, d2, d3 или d4

roller <- rollapplyr(ar1, 30,FUN=modwt,wf="la8",n.levels=4,boundary="periodic")

Результатом этого является большая матрица со следующей структурой:

> str(roller)
List of 855
 $ : num [1:30] 0.117 -0.138 0.199 -1.267 1.872 ...
 $ : num [1:30] -0.171 0.453 -0.504 -0.189 0.849 ...
 $ : num [1:30] 0.438 -0.3868 0.1618 -0.0973 -0.0247 ...
 $ : num [1:30] -0.418 0.407 0.639 -2.013 1.349 ...

... пропущено много строк ...

$ : num [1:30] 0.307 -0.658 -0.105 1.128 -0.978 ...
  [list output truncated]
 - attr(*, "dim")= int [1:2] 171 5
 - attr(*, "dimnames")=List of 2
  ..$ : NULL
  ..$ : chr [1:5] "d1" "d2" "d3" "d4" ...

Как я могу настроить переменную так, чтобы она хранила (200-30) +1 списки со списками внутри этого для каждой из шкал d1, d2, d3 и d4?

Для воспроизводимого примера используйте следующее:

library(waveslim)
data(ar1)
ar1.modwt <- modwt(ar1, "la8", 4)

person TheGoat    schedule 12.08.2017    source источник


Ответы (1)


Определите modwt2, который вызывает modwt, берет первые 4 компонента и преобразует их в числовой вектор. Затем используйте rollapplyr с этим заданием rollr, где каждая строка rollr является результатом одного вызова modwt2. Наконец, преобразовать каждую строку rollr в отдельную матрицу и создать список L этих матриц:

modwt2 <- function(...) unlist(head(modwt(...), 4))
rollr <- rollapplyr(ar1, 30, FUN = modwt2, wf = "la8", n.levels = 4, boundary = "periodic")
L <- lapply(1:nrow(rollr), function(i) matrix(rollr[i,], , 4))

Если требуется массив 30 x 4 x 171, то следующее упростит его в трехмерный массив:

simplify2array(L)

или в виде списка списков:

lapply(L, function(x) as.list(as.data.frame(x)))

2) Это альтернативное решение, которое просто использует lapply напрямую и возвращает список, каждый из компонентов которого является списком, состоящим из d1, d2, d3 и d4.

lapply(1:(200-30+1), function(i, ...) head(modwt(ar1[seq(i, length = 30)], ...), 4),
  wf = "la8", n.levels = 4, boundary = "periodic")

Обновления: улучшения кода, разверните (1) и добавьте (2).

person G. Grothendieck    schedule 13.08.2017
comment
не возражаете, если я укажу на этот вопрос в новом вопросе, основанном на этом ответе? Я совершенно не разбираюсь в этом, и единственный способ добраться туда, где мне нужно, - это разбить вопросы на более управляемые части. - person TheGoat; 14.08.2017
comment
Это нормально, когда один вопрос ссылается на другой, когда они связаны между собой, так что это определенно будет нормально. - person G. Grothendieck; 14.08.2017
comment
Спасибо за помощь с этим вопросом, мне жаль, что я не разбирался в R так же хорошо, как вы. Я создал еще один вопрос здесь, и мне действительно нужна помощь с ним так что я собираюсь поставить 300 баллов за награду. Не знаю, смотрели ли вы на это, но если бы вы могли, я был бы очень благодарен. Баунти начнется через 23 часа. - person TheGoat; 15.08.2017