是否有一种既方便又优雅的方法可以在逻辑时间序列中找到包含True或1值的连续区域?我正在寻找一些返回表单摘要的东西:
Region_id Start Stop
1 YYYY-MM-DD HH:MM:SS YYYY-MM-DD HH:MM:SS
2 YYYY-MM-DD HH:MM:SS YYYY-MM-DD HH:MM:SS
... etc
示例输入ts:
mins <- function (N, from = as.character(Sys.time()), cols = 1, by = 1)
{
deltas <- seq(from = 0, by = 60 * by, length.out = N)
nacol <- matrix(data = NA, ncol = cols, nrow = N)
xts(x = nacol, order.by = strptime(from, format = "%Y-%m-%d %H:%M") +
deltas)
}
d <- mins(N=20,cols=1)
d[,1] <- F; d[5:12,1] <- T; d[14:20,1] <- T
d
[,1]
2012-12-18 20:48:00 FALSE
2012-12-18 20:49:00 FALSE
2012-12-18 20:50:00 FALSE
2012-12-18 20:51:00 FALSE
2012-12-18 20:52:00 TRUE
2012-12-18 20:53:00 TRUE
2012-12-18 20:54:00 TRUE
2012-12-18 20:55:00 TRUE
2012-12-18 20:56:00 TRUE
2012-12-18 20:57:00 TRUE
2012-12-18 20:58:00 TRUE
2012-12-18 20:59:00 TRUE
2012-12-18 21:00:00 FALSE
2012-12-18 21:01:00 TRUE
2012-12-18 21:02:00 TRUE
2012-12-18 21:03:00 TRUE
2012-12-18 21:04:00 TRUE
2012-12-18 21:05:00 TRUE
2012-12-18 21:06:00 TRUE
2012-12-18 21:07:00 TRUE
# so far for the _idealized_ input, now the function I am looking for to return data.frame
# like this for the d object as above:
Region_id Start Stop
1 2012-12-18 20:52:00 2012-12-18 20:59:00
2 2012-12-18 21:01:00 2012-12-18 21:07:00
这可能是二进制信号处理的常见任务,因此值得研究。当然,它是理想化的。只是开始。现实情况将更加复杂。
首先,使用rle
查找连续的块,然后创建一个指示符来分隔每个块。
r <- rle(coredata(d)[,1])
ind <- rep(seq_along(r$lengths), r$lengths)
现在,您可以使用指示符来分割xts对象,并在每个连续块上运行min/max函数。
s <- split(index(d), ind)
l <- lapply(s, function(x) data.frame(start=min(x), stop=max(x)))
然后,您可以将上述结果rbind
合并到一个data.frame中,创建region
列,只对TRUE
值进行子集设置,并获取累积和。请注意,由于时区差异,我的时间不同,但这个概念是正确的。
out <- do.call(rbind, l)
out$region <- r$values
out <- out[out$region,]
out$region <- cumsum(out$region)
out
# start stop region
# 2 2012-12-18 20:45:00 2012-12-18 20:52:00 1
# 4 2012-12-18 20:54:00 2012-12-18 21:00:00 2