R: функция скользящего окна с регулируемым окном и размером шага для нерегулярно расположенных наблюдений

Скажем, есть фрейм данных из 2 столбцов с столбцом времени или расстояния, который последовательно увеличивается, и столбцом наблюдения, который может иметь NA здесь и там. Как эффективно использовать функцию скользящего окна, чтобы получить некоторую статистику, скажем, среднее значение для наблюдений в окне длительностью X (например, 5 секунд), сдвинуть окно в течение Y секунд (например, 2,5 секунды), повторить ...Количество наблюдений в окне основано на столбце времени, таким образом, количество наблюдений на окно и количество наблюдений для скольжения окна могут варьироваться Функция должна принимать любой размер окна, вплоть до количества наблюдений и размера шага.

Вот пример данных (см.Редактировать:«для большего набора образцов)

set.seed(42)
dat <- data.frame(time = seq(1:20)+runif(20,0,1))
dat <- data.frame(dat, measure=c(diff(dat$time),NA_real_))
dat$measure[sample(1:19,2)] <- NA_real_
head(dat)
      time   measure
1 1.914806 1.0222694
2 2.937075 0.3490641
3 3.286140        NA
4 4.830448 0.8112979
5 5.641746 0.8773504
6 6.519096 1.2174924

Желаемый вывод для конкретного случая 5-секундного окна, 2,5-секундного шага, первого окна от -2,5 до 2,5, na.rm = FALSE:

 [1] 1.0222694
 [2]        NA
 [3]        NA
 [4] 1.0126639
 [5] 0.9965048
 [6] 0.9514456
 [7] 1.0518228
 [8]        NA
 [9]        NA
[10]        NA

Пояснение: В желаемом выводе самое первое окно ищет времена между -2.5 и 2.5. В этом окне есть одно наблюдение меры, и оно не является NA, поэтому мы получаем это наблюдение: 1.0222694. Следующее окно - от 0 до 5, и в этом окне есть NA, поэтому мы получаем NA. То же самое для окна от 2,5 до 7,5. Следующее окно с 5 до 10. В окне 5 наблюдений, ни одно из которых не является NA. Итак, мы получаем среднее из этих 5 наблюдений (то есть среднее (dat [dat $ time> 5 & dat $ time <10, 'measure']))

Что я пробовал: Вот что я пробовал для конкретного случая окна, где размер шага составляет 1/2 длительности окна:

windo <- 5  # duration in seconds of window

# partition into groups depending on which window(s) an observation falls in
# When step size >= window/2 and < window, need two grouping vectors
leaf1 <- round(ceiling(dat$time/(windo/2))+0.5)
leaf2 <- round(ceiling(dat$time/(windo/2))-0.5) 

l1 <- tapply(dat$measure, leaf1, mean)
l2 <- tapply(dat$measure, leaf2, mean)

as.vector(rbind(l2,l1))

Не гибкий, не элегантный, не эффективный. Если размер шага не равен 1/2 размера окна, подход не будет работать, как есть.

Есть мысли по поводу общего решения такого рода проблем? Любое решение приемлемо. Чем быстрее, тем лучше, хотя я предпочитаю решения, использующие базы R, data.table, Rcpp и / или параллельные вычисления. В моем реальном наборе данных, есть несколько миллионов наблюдений, содержащихся в списке фреймов данных (максимальный фрейм данных ~ 400 000 наблюдений).

Ниже приводится дополнительная информация: большой выборочный набор

Редактировать: В соответствии с запросом, здесь приведен более крупный, более реалистичный пример набора данных с большим количеством NA и минимальным промежутком времени (~ 0,03). Для ясности, однако, список фреймов данных содержит небольшие, такие как приведенные выше, а также такие, как следующие и более крупные:

set.seed(42)
dat <- data.frame(time = seq(1:50000)+runif(50000, 0.025, 1))
dat <- data.frame(dat, measure=c(diff(dat$time),NA_real_))
dat$measure[sample(1:50000,1000)] <- NA_real_
dat$measure[c(350:450,3000:3300, 20000:28100)] <- NA_real_
dat <- dat[-c(1000:2000, 30000:35000),] 

# a list with a realistic number of observations:
dat <- lapply(1:300,function(x) dat)

Ответы на вопрос(5)

Ваш ответ на вопрос