在一段时期内按群组查找日期
问题描述:
我有一个有许多ID的面板,begin
和end
日期。 begin
到end
日期创建一个interval
的时间。在一段时期内按群组查找日期
id begin end interval overlap
1: 1 2010-01-31 2011-06-30 2009-08-04 UTC--2011-12-27 UTC TRUE
2: 1 2011-01-31 2012-06-30 2010-08-04 UTC--2012-12-27 UTC TRUE
3: 1 2012-01-31 2013-06-30 2011-08-04 UTC--2013-12-27 UTC TRUE
4: 1 2013-01-31 2014-06-30 2012-08-04 UTC--2014-12-27 UTC TRUE
5: 1 2013-02-28 2013-07-31 2012-09-01 UTC--2014-01-27 UTC TRUE
6: 1 2015-02-28 2015-03-31 2014-09-01 UTC--2015-09-27 UTC TRUE
7: 1 2015-06-30 2015-07-31 2015-01-01 UTC--2016-01-27 UTC TRUE
8: 1 2015-09-30 2016-01-31 2015-04-03 UTC--2016-07-29 UTC TRUE
9: 2 2010-01-31 2011-06-30 2009-08-04 UTC--2011-12-27 UTC TRUE
10: 2 2011-01-31 2012-06-30 2010-08-04 UTC--2012-12-27 UTC TRUE
11: 2 2012-01-31 2013-06-30 2011-08-04 UTC--2013-12-27 UTC TRUE
12: 2 2013-01-31 2014-06-30 2012-08-04 UTC--2014-12-27 UTC TRUE
13: 2 2013-02-28 2013-07-31 2012-09-01 UTC--2014-01-27 UTC TRUE
14: 2 2015-02-28 2015-03-31 2014-09-01 UTC--2015-09-27 UTC TRUE
15: 2 2015-06-30 2015-07-31 2015-01-01 UTC--2016-01-27 UTC TRUE
16: 2 2015-09-30 2016-01-31 2015-04-03 UTC--2016-07-29 UTC TRUE
我需要测试是否,对于每个ID,任何begin
/end
日期被包括在另一interval
(同一ID的)。
例如,id1
begin
(2010-01-31)中不包括的id1
比在第一线中的任何其他时间段。但是,id1
end
日期(2011-06-30)包含在第二行(2010-08-04 UTC - 2012-12-27 UTC)的区间中。
我试图lubridate
间隔和数据表%within%
但因为它被包含在其相应的周期它产生TRUE。我需要知道它是否包含在同一个ID的任何其他时期。
customer[begin %within% interval | end %within% interval, overlap := TRUE, by = id]
我已经检查的data.table foverlap,但似乎设计用于连接不同的表和其它问题,只是载体,但not panels有间隔。
任何想法?
数据:
structure(list(id = c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2,
2, 2, 2), begin = structure(c(14640, 15005, 15370, 15736, 15764,
16494, 16616, 16708, 14640, 15005, 15370, 15736, 15764, 16494,
16616, 16708), class = "Date"), end = structure(c(15155, 15521,
15886, 16251, 15917, 16525, 16647, 16831, 15155, 15521, 15886,
16251, 15917, 16525, 16647, 16831), class = "Date"), interval = structure(c(75600000,
75686400, 75686400, 75600000, 44323200, 33782400, 33782400, 41731200,
75600000, 75686400, 75686400, 75600000, 44323200, 33782400, 33782400,
41731200), start = structure(c(1249344000, 1280880000, 1312416000,
1344038400, 1346457600, 1409529600, 1420070400, 1428019200, 1249344000,
1280880000, 1312416000, 1344038400, 1346457600, 1409529600, 1420070400,
1428019200), tzone = "UTC", class = c("POSIXct", "POSIXt")), tzone = "UTC", class = structure("Interval", package = "lubridate")),
overlap = c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE)), .Names = c("id",
"begin", "end", "interval", "overlap"), row.names = c(NA, -16L
), class = c("data.table", "data.frame"), .internal.selfref = <pointer: 0x0000000000140788>)
答
下面是做到这一点,利用int_overlaps
从lubridate
的一种方式。我已经定义了开始日期和结束日期的时间间隔,但是在您的数据中它们是不同的 - 也许您可以澄清哪些是正确的。
library(lubridate)
df$interval <- interval(as.POSIXct(df$begin),as.POSIXct(df$end))
df <- df[order(df$id),] #needs to be sorted by id for next stage to work
df$overlap <- unlist(tapply(df$interval, #loop through intervals
df$id, #grouped by id
function(x) rowSums(outer(x,x,int_overlaps))>1))
#check if more than one overlap in subset for that id
df
id begin end interval overlap
1 1 2010-01-31 2011-06-30 2010-01-31 UTC--2011-06-30 UTC TRUE
2 1 2011-01-31 2012-06-30 2011-01-31 UTC--2012-06-30 UTC TRUE
3 1 2012-01-31 2013-06-30 2012-01-31 UTC--2013-06-30 UTC TRUE
4 1 2013-01-31 2014-06-30 2013-01-31 UTC--2014-06-30 UTC TRUE
5 1 2013-02-28 2013-07-31 2013-02-28 UTC--2013-07-31 UTC TRUE
6 1 2015-02-28 2015-03-31 2015-02-28 UTC--2015-03-31 UTC FALSE
7 1 2015-06-30 2015-07-31 2015-06-30 UTC--2015-07-31 UTC FALSE
8 1 2015-09-30 2016-01-31 2015-09-30 UTC--2016-01-31 UTC FALSE
9 2 2010-01-31 2011-06-30 2010-01-31 UTC--2011-06-30 UTC TRUE
10 2 2011-01-31 2012-06-30 2011-01-31 UTC--2012-06-30 UTC TRUE
11 2 2012-01-31 2013-06-30 2012-01-31 UTC--2013-06-30 UTC TRUE
12 2 2013-01-31 2014-06-30 2013-01-31 UTC--2014-06-30 UTC TRUE
13 2 2013-02-28 2013-07-31 2013-02-28 UTC--2013-07-31 UTC TRUE
14 2 2015-02-28 2015-03-31 2015-02-28 UTC--2015-03-31 UTC FALSE
15 2 2015-06-30 2015-07-31 2015-06-30 UTC--2015-07-31 UTC FALSE
16 2 2015-09-30 2016-01-31 2015-09-30 UTC--2016-01-31 UTC FALSE