我有一个包含日期的大数据框,需要连续检查第一个日期,如下所示:
ID ID_2 END BEG
1 55 2017-06-30 2016-01-01
1 55 2015-12-31 2015-11-12 --> Gap (required date)
1 88 2008-07-26 2003-02-24
2 19 2014-09-30 2013-05-01
2 33 2013-04-30 2011-01-01 --> Not Gap (overlapping)
2 19 2012-12-31 2011-01-01
2 33 2010-12-31 2008-01-01
2 19 2007-12-31 2006-01-01
2 19 2005-12-31 1980-10-20 --> No actual Gap(required date)
如图所示,并非所有日期都重叠,因此我需要按ID(不是ID_2)返回出现第一个间隔(时间倒退)的日期。我试过使用for,但是它非常慢(数据帧有15万行)。我一直在搞怪dplyr和mutate,如下所示:
df <- df%>%
group_by(ID)%>%
mutate(END_lead = lead(END))
df$FLAG <- df$BEG - days(1) == df$END_lead
df <- df%>%
group_by(ID)%>%
filter(cumsum(cumsum(FLAG == FALSE))<=1)
但是这组指令在第一个重叠处停止,过滤了错误的日期。我已经尝试过我能想到的一切,以降序或升序排序,并使用min和max,但找不到解决方案。
所需的实际结果是:
ID ID_2 END BEG
1 55 2015-12-31 2015-11-12
2 19 2008-07-26 1980-10-20
是否可以使用dplyr,tidyr和lubridate做到这一点?
答案 0 :(得分:1)
使用dplyr
的可能解决方案:
library(dplyr)
df %>%
mutate_at(vars(END, BEG), funs(as.Date)) %>%
group_by(ID) %>%
slice(which.max(BEG > ( lead(END) + 1 ) | is.na(BEG > ( lead(END) + 1 ))))
使用您的最新数据,它会给出:
# A tibble: 2 x 4
# Groups: ID [2]
ID ID_2 END BEG
<int> <int> <date> <date>
1 1 55 2015-12-31 2015-11-12
2 2 19 2005-12-31 1980-10-20
该解决方案的作用基本上是:
Date
格式(不需要lubridate
); ID
分组; TRUE
),或者如果没有空格,则它是第一行(这意味着在检查时缺少值)差距,这就是is.na(BEG > ( lead(END) + 1 ))
)的原因。答案 1 :(得分:0)
我会使用xts包,首先为您拥有的每个ID创建xts对象,而不是对每个对象使用first()和last()函数。