Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 按日期分组ID_R - Fatal编程技术网

R 按日期分组ID

R 按日期分组ID,r,R,我有一个三列的数据表id,dtstart,dtend。例如: id开始结束 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/2

我有一个三列的数据表id,dtstart,dtend。例如:

id开始结束
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

干杯
Andrew

这可以使用
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))
dt.new%
排列(id、开始、结束)%>%
突变(gr=cumsum(滞后(id,默认值=min(id))!=id|
as.numeric(difftime(开始,延迟(结束,默认值=第一个(开始)),单位=‘天’)>1))%>%
分组依据(id,gr)%>%
总结(开始=第一个(开始),
结束=最后(结束))
结果是:

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    
来源:本地数据帧[6 x 4]
组:id[?]
id gr起始端
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天。

再次感谢@akash87

例如,下面的第6行在一个月内,因此它仍应返回id 1从2006年2月1日到2006年9月30日的一行,但它分为两行,第一行从2006年2月1日到2006年6月12日,然后从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

安德鲁

我想这可能会让你走:谢谢。cumsum正在为我制作NAs。我尝试使用.numeric(as.Date(start,format=“%Y-%m-%d”)-lag(as.Date(end,format=“%Y-%m-%d”))>1),但第一个grp条目是NA,因此在分组和汇总时会包含该条目。您必须在
lag()
中添加
默认值
参数。我更新了我的代码。谢谢@akash87。只有一个错误,当它应该是一个时,它会分成两个。例如,如果第3行为:1 05/02/2007 05/02/2007。这一行是单独分开的。我没有得到那个错误,你能发送一个例子吗?Will do@akash87,我把它放在对原始问题的回答中,并列出了例子。这让我抓狂。啊,这带来了一个不同的问题:您正在同一列中的其他日期范围内查找日期范围。我想,一个不太优雅的原因是在新表上再次运行它,将摘要(…end=last(end))替换为摘要(…end=max(end))??我使用cumsum得到的日期范围条件(lag(id,default=min(id))!=id |!(dtstart%in%min(dtstart):max(dtend)),但是添加difftime子句会覆盖它。