在给定时间内对 R 中发生的事件进行分组 frame/period
Grouping events in R that occur withing a given time frame/period
我目前正在使用 R。我有大量 table 带有小时时间戳的数据,以及每小时的观察值。我需要将所有在 4 小时内发生的 > 0 的观察结果分组为一个事件。示例数据如下:
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 创建一个非事件。对此有简单的解决方案吗?谢谢
这是一个使用 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
到那时,您可以 follow-up 对您的群组进行任何您想做的事情。例如按组计算平均值,
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
我目前正在使用 R。我有大量 table 带有小时时间戳的数据,以及每小时的观察值。我需要将所有在 4 小时内发生的 > 0 的观察结果分组为一个事件。示例数据如下:
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 创建一个非事件。对此有简单的解决方案吗?谢谢
这是一个使用 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
到那时,您可以 follow-up 对您的群组进行任何您想做的事情。例如按组计算平均值,
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