按日期分组ID

时间:2017-06-12 19:40:08

标签: r

我有一个包含三列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。

干杯 安德鲁

2 个答案:

答案 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

安德鲁