我有一个包含三列id,dtstart,dtend的数据表。例如:
id start end
1 01/01/2015 31/01/2015
1 02/02/2015 28/02/2015
1 01/07/2016 31/07/2016
1 01/08/2016 31/08/2016
2 01/03/2015 31/03/2015
2 01/04/2015 30/04/2015
2 01/02/2016 28/02/2016
2 01/03/2016 31/03/2016
...
我需要创建另一个按ID分组且具有相同列的数据表,但新的开始日期是原始开始日期的最小日期,新的结束日期是原始dtend中的最大日期。
如果在结束日期和下一个开始日期之间有超过一天的休息时间,那么它应该单独分组。
例如,对于上述内容,新表将是:
id start end
1 01/01/2015 28/02/2015
1 01/07/2016 31/08/2016
2 01/03/2015 30/04/2016
2 01/02/2016 31/03/2016
...
我是否需要for循环或是否有更有效的方法(例如数据表分组)?该表超过2000万行,具有100k +唯一ID。
干杯 安德鲁
答案 0 :(得分:0)
可以使用dplyr
dt.new <- dt %>%
arrange(id, start, end) %>%
mutate(gr = cumsum(lag(id, default = min(id)) != id |
as.numeric(difftime(start, lag(end, default = first(start)), units = 'days')) > 1)) %>%
group_by(id, gr) %>%
summarise(start = first(start),
end = last(end))
结果是:
Source: local data frame [6 x 4]
Groups: id [?]
id gr start end
<int> <int> <dttm> <dttm>
1 1 0 2015-01-01 2015-01-31
2 1 1 2015-02-02 2015-02-28
3 1 2 2016-07-01 2016-08-31
4 2 3 2015-03-01 2015-04-30
5 2 4 2016-02-01 2016-02-28
6 2 5 2016-03-01 2016-03-31
这有效并且与您的输出不匹配,因为您请求了一天保证金(如果您想要两天保证金,然后从>1
切换到>2
),2016年是闰年,这是R的内部日历。因此2016年2月28日至2016年3月1日之间的差额为2天。
答案 1 :(得分:0)
再次感谢@ akash87
例如,下面的第6行是在一个月之内,所以从1/02/2006到30/09/2006它仍然应该为id 1返回一行,但它会分成两行,第一行从2006年2月1日到12月12日/ 06/2006,然后从2006年7月1日到2016年9月30日
id dtstart dtend
1 01/02/2006 28/02/2006
1 01/03/2006 31/03/2006
1 01/04/2006 30/04/2006
1 01/05/2006 31/05/2006
1 01/06/2006 30/06/2006
1 10/06/2006 12/06/2006
1 01/07/2006 31/07/2006
1 01/08/2006 31/08/2006
1 01/09/2006 30/09/2006
2 01/04/2006 30/04/2006
2 01/05/2006 31/05/2006
2 01/09/2006 30/09/2006
2 01/10/2006 31/10/2006
所以不要回来
id start end
1 01/02/2006 30/09/2006
2 01/04/2006 31/05/2006
2 01/09/2006 31/10/2006
我们有
id start end
1 01/02/2006 12/06/2006
1 01/07/2006 30/09/2006
2 01/04/2006 31/05/2006
2 01/09/2006 31/10/2006
安德鲁