Группировка событий в R, которые происходят с заданным периодом времени / периодом

В настоящее время я использую R. У меня есть большая таблица данных с отметкой часового времени и наблюдением за каждым часом. Мне нужно сгруппировать все наблюдения> 0, которые происходят в течение 4 часов друг от друга, как одно событие. Пример данных ниже:

Date            Obs
2017-12-01 5    0.01
2017-12-01 6    0.5
2017-12-01 7    0.2
2017-12-01 8    0
2017-12-01 9    0.03
2017-12-01 10   0.01
2017-12-01 11   0
2017-12-01 12   0
2017-12-01 13   0
2017-12-01 14   0
2017-12-01 15   0
2017-12-01 16   0
2017-12-01 17   0
2017-12-01 18   1.2
2017-12-01 19   0.6 

Например, первые шесть строк будут одним событием (0,01, 0,5, 0,2, 0, 0,03, 0,01), поскольку существует только один час отсутствия наблюдения (ноль). Тогда последовательные строки из 4 нулей или более вызовут не-событие. Событие 2 начнется в следующий раз, когда у нас будет положительное значение (1.2, 0.6) и т. Д.

Я попытался сделать это с помощью функции rle(). Например:

events <- rle(data$Obs > 0)

Однако это создает не-событие для каждого 0. Есть ли простое решение для этого? Благодарю.

1 ответ

Решение

Вот решение с использованием нотации data.table с использованием длин серий, чтобы определить, достаточно ли длинен регион для разделения групп:

library(data.table)
set.seed(120)

# Toy data set
dat <- data.table(time=seq(1,1000), obs=sample(c(0,0.01, 0.1, 1), size=1000, replace=TRUE, prob=c(0.3, 0.3, 0.3, 0.1)))

# calculate run lengths for the observation values
o <- rle(dat$obs)

# assign a new column assigning each row(timepoint/observation) its run length
dat[, length := unlist(lapply(o$lengths, function(x) rep(x, each=x)))]

# determine if the region should be considered an "interruption"
dat[, interrupt := ifelse(obs==0 & length>= 4, TRUE, FALSE)]

# assign values to each alternating interruption/grouped region
dat[, group := rleid(interrupt)]

# Remove sections with >= 4 obsevations of 0
dat2 <- dat[interrupt==FALSE]

# Re-number groups starting at 1
dat2[,group := as.numeric(as.factor(group))]

что должно дать вам то, что вы ищете

time  obs length interrupt group
   1 0.00      2     FALSE     1
   2 0.00      2     FALSE     1
   3 0.01      1     FALSE     1
   4 1.00      1     FALSE     1
   5 0.01      1     FALSE     1

 992 0.10      1     FALSE     6
 993 0.00      1     FALSE     6
 994 0.01      1     FALSE     6
 995 0.00      1     FALSE     6
 996 0.10      1     FALSE     6

На этом этапе вы можете следить за тем, что вы хотите делать со своими группами. Например, вычисление среднего по группе,

dat2[, list("average"=mean(obs)), by=group]

доходность

group   average
    1 0.1391803
    2 0.1415838
    3 0.2582716
    4 0.1353086
    5 0.1011765
    6 0.1896774
Другие вопросы по тегам