R: Função da janela de rolamento com janela ajustável e tamanho de degrau para observações com espaçamento irregular

Digamos que exista um quadro de dados de duas colunas com uma coluna de tempo ou distância que aumenta sequencialmente e uma coluna de observação que pode ter NAs aqui e ali. Como posso usar eficientemente uma função de janela deslizante para obter alguma estatística, digamos, média, para as observações em uma janela de duração X (por exemplo, 5 segundos), deslize a janela por Y segundos (por exemplo, 2,5 segundos), repita ...O número de observações na janela é baseado na coluna de tempo, portanto, o número de observações por janela e o número de observações para deslizar a janela podem variar A função deve aceitar qualquer tamanho de janela até o número de observações e um tamanho de etapa.

Aqui estão os dados de amostra (consulte "Editar:"para um conjunto de amostras maior)

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

Saída desejada para o caso específico de uma janela de 5 segundos, etapa de 2,5 segundos, primeira janela de -2,5 a 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

Explicação: Na saída desejada, a primeira janela procura tempos entre -2,5 e 2,5. Uma observação de medida está nesta janela, e não é um NA, assim obtemos essa observação: 1.0222694. A próxima janela é de 0 a 5, e existe um NA na janela, então obtemos NA. O mesmo para a janela de 2,5 a 7,5. A próxima janela é de 5 a 10. Existem 5 observações na janela, nenhuma é NA. Portanto, obtemos a média dessas 5 observações (ou seja, média (dat [dat $ time> 5 e dat $ time <10, 'measure']))

O que eu tentei: Aqui está o que eu tentei no caso específico de uma janela em que o tamanho da etapa é 1/2 da duração da janela:

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))

Não é flexível, não é elegante, não é eficiente. Se o tamanho da etapa não for 1/2 da janela, a abordagem não funcionará como está.

Alguma idéia de uma solução geral para esse tipo de problema? Qualquer solução é aceitável. Quanto mais rápido, melhor, embora eu prefira soluções usando base R, data.table, Rcpp e / ou computação paralela. No meu conjunto de dados real, existem vários milhões de observações contidas em uma lista de quadros de dados (o quadro máximo de dados é ~ 400.000 observações).

Abaixo está uma informação extra: Um conjunto de amostras maior

Editar: Conforme solicitação, aqui está um exemplo de conjunto de dados maior e mais realista, com muito mais NAs e o tempo mínimo (~ 0,03). Porém, para ficar claro, a lista de quadros de dados contém quadros pequenos como o acima, assim como os seguintes e maiores:

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)

questionAnswers(5)

yourAnswerToTheQuestion