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)