R语言Lubridate包如何在一个连续时间范围和一组时间段之间找到非重叠的时期

4

我有以下时间范围:

A <- c('2016-01-01', '2019-01-05')
B <- c('2017-05-05','2019-06-05')

X_Period <- interval("2015-01-01", "2019-12-31")
Y_Periods <- interval(A, B)

我希望找到X_Period和Y_Periods之间没有重叠的时间段,结果应为:
[1]'2015-01-01'--'2015-12-31'
[2]'2017-05-06'--'2019-01-04'
[3]'2019-06-06'--'2019-31-12'

我试图使用setdiff,但它无法正常工作

setdiff(X_Period, Y_Periods)

我已将“2019-31-11”更改为“2019-12-31”。我猜这就是预期的结果。如果不是,请折叠回去。 - kangaroo_cliff
是的,现在是正确的。 - ashwin agrawal
1个回答

2

这里有一个选项:

library(lubridate)
seq_X <- as.Date(seq(int_start(X_Period), int_end(X_Period), by = "1 day"))
seq_Y <- as.Date(do.call("c", sapply(Y_Periods, function(x)
    seq(int_start(x), int_end(x), by = "1 day"))))

unique_dates_X <- seq_X[!seq_X %in% seq_Y]

lst <- aggregate(
    unique_dates_X,
    by = list(cumsum(c(0, diff.Date(unique_dates_X) != 1))),
    FUN = function(x) c(min(x), max(x)),
    simplify = F)$x    

lapply(lst, function(x) interval(x[1], x[2]))
#[[1]]
#[1] 2015-01-01 UTC--2015-12-31 UTC
#
#[[2]]
#[1] 2017-05-06 UTC--2019-01-04 UTC
#
#[[3]]
#[1] 2019-06-06 UTC--2019-12-31 UTC

这个策略是将interval转换为按天序列(一个用于X_Period,另一个用于Y_Period); 然后我们找到所有仅属于X_Period(而不属于Y_Periods)的日期。然后我们进行聚合以确定连续日期子序列中的第一个和最后一个日期。生成的lst是具有这些起始/结束日期的list。要转换为interval,我们只需循环遍历list并将起始/结束日期转换为interval即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接