Я рассмотрел несколько инструментов для создания скользящего или скользящего среднего (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 () могут быть далее использованы для получения результата по ряду данных, но я не понимаю, как можно применить это к многодневному окну.
В приведенном ниже примере, где есть:
для окна усреднения из 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: это сводка инструментов манипулирования и анализа временных рядов может быть полезной, но довольно ... плотны .