функция перемещения применяется к циклическим данным с прерывистым окном - PullRequest
0 голосов
/ 14 февраля 2019

Я рассмотрел несколько инструментов для создания скользящего или скользящего среднего (rollapply (); filter (); runmean (); group_by () & sumrize ()), которые предполагают непрерывный ряд данных.

Однако я хочу применить функцию к повторяющемуся движущемуся окну в циклических данных, поэтому окно необходимо обернуть вокруг конца ряда данных.

В частности, например, чтобы найти среднее значение30 дней ежедневных данных из 20-летних данных за каждый день года, т.е. дают 366 значений.Интересный момент здесь - и там, где подобные rollapply (), кажется, не используются - это то, что, например, опять же, значение для дня 10 (с 29 дней до 10 января каждого года) включает 20 дней вконец последнего года ряда данных.

В другом месте представлено простое решение ( R среднегодовое значение ) для получения среднесуточного значения и sd из многолетних данных с необходимымиwrap:

require(tibble)
require(lubridate)
require(dplyr)
df <- tibble(date=seq.Date(from=as.Date("1968-10-01"), to=as.Date("1973-09-30"), by="days"),
          value=runif(length(date)))

df %>%
  group_by(dayIdx = yday(date)) %>%
  summarise(mean_val = mean(value, na.rm=TRUE), sd_val = sd(value, na.rm=TRUE))

и group_by () могут быть далее использованы для получения результата по ряду данных, но я не понимаю, как можно применить это к многодневному окну.

В приведенном ниже примере, где есть:

  • 12 значений (проиндексированных как 0:11) за период (т. Е. Год) и

  • 5 периодов,

  • серия данных состоит из 60 записей (1:60) и

для окна усреднения из 3 записей:

  • вторая запись результата (индекс 1), функции mean () и sd () применяются к записям:

    1,2,12,13,14,24,25,26,36,37,38,48,49,50,60

    со значениями индекса 0,1,11.

Насколько я понимаю, rollapply () запись 60 не будет включена.

Чтобы сделать это более интересным, я работаю с несколькими рядами данных различной длины (число лет) и несколько окон усреднения.

Я могу получить функциональный результат, используя циклы for .., но я уверен, что есть какой-то хитрый подход, который ускользает от меня.

require(dplyr)
require(tibble)
##create data
num_series <- 3 #the number of dataseries
len_period <- 12 #number of records per 'year'
num_periods <- 5 #number of 'years'
df <- tibble(series_id = rep(1:num_series, each = num_periods *  len_period), rec_num = rep(1:(len_period * num_periods), times = num_series), idx = rep(0:(len_period-1), times = num_series * num_periods) , data_val = runif(length(idx)))

## vector of averaging windows
av_window <- c(3, 6, 9)

##prepare empty tibble
result <- tibble(series_id = rep(1:num_series, each = length(av_window) * len_period), idx = rep(0:(len_period-1), times = length(av_window) * num_series), av_win = rep(rep(av_window, each = len_period), times = num_series), win_start = (idx - av_win + 1) %% len_period, val_mean = 0.0, val_sd = 0.0)

## loop through data series
data_series <- distinct(result, series_id)
for (id in data_series$series_id){
  ##loop through averaging windows
  for (av_win_val in av_window){
    ##loop through record indices
    for (idx_val in (0:(len_period-1))){
      dfTemp <- subset(df, (series_id == id) & (idx %in% ((idx_val + ((-av_win_val + 1):0)) %% len_period)))
      logical_vec <- result$series_id == id & result$av_win == av_win_val & result$idx == idx_val
      result[logical_vec, "val_mean"] <- mean(dfTemp$data_val, na.rm =TRUE)
      result[logical_vec, "val_sd"] <- sd(dfTemp$data_val, na.rm =TRUE)
    }
  }    
} 

КонцептуальноОдно из решений может состоять в том, чтобы преобразовать данные в строки «дней» и столбцы «лет», а затем применить функцию ко всем значениям в движущемся 2D-блоке, но это все равно не решает циклический аспект этой проблемы.Тем не менее, можно представить расширение этой концепции на третье измерение для нескольких баз данных.

Любые предложения будут тепло приветствоваться - JS

РЕДАКТИРОВАТЬ: из ХэдлиWickham's split-apply-compbine (plyr) paper :

Обратите внимание, что plyr строго полагает, что каждый фрагмент данных будет обрабатываться только один раз и независимо от всех остальных фрагментов.Это означает, что вы не можете использовать эти инструменты, когда каждая итерация требует перекрывающихся данных (например, скользящего среднего), или это зависит от предыдущей итерации (как в динамическом моделировании).Циклы по-прежнему наиболее подходят для этих задач.

EDIT2: это сводка инструментов манипулирования и анализа временных рядов может быть полезной, но довольно ... плотны .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...