按组查找下一个日期系列

5

我有这样的一些数据:

sample.data <- rbind(data.table(start.date=seq(from=as.Date("2010-01-01"), to=as.Date("2014-12-01"), by="quarter"),
                 Group=c("A","B","C","D"), rnorm(20, 5)),
                 data.table(start.date=seq(from=as.Date("2010-01-01"), to=as.Date("2014-12-01"), by="quarter"),
                 Group=c("A","B","C","D"), rnorm(20, 3))
                 )

我想要创建一个名为end.date的列,该列等于每个分组中下一个最早的start.date值。
例如,对于Group==A的第一个start.date2010-01-01。对于Group==A的下一个最早的start.date2011-01-01。因此,在按Group排序时,最终结果应如下所示:
                start.date Group   end.date
                2010-01-01     A 2011-01-01
                2010-01-01     A 2011-01-01
                2011-01-01     A 2012-01-01
                2011-01-01     A 2012-01-01
                2012-01-01     A 2013-01-01
                2012-01-01     A 2013-01-01
                2013-01-01     A 2014-01-01
                2013-01-01     A 2014-01-01
                2014-01-01     A         NA
                2014-01-01     A         NA
                2010-04-01     B 2011-04-01
                2010-04-01     B 2011-04-01
                2011-04-01     B 2012-04-01
                2011-04-01     B 2012-04-01

等等。理想情况下,我希望能够通过参考来完成这个过程,就像

sample.data [,end.date:= EXPRESSION]

但我不知道从哪里开始。谢谢任何帮助。

3个回答

5

好的,所以:

events = unique(sample.data[ , .(Group, start.date) ])
events[, next.date := shift(start.date, type="lead"), by=Group]

sample.data[events, on=c("Group", "start.date"), end.date := next.date ]

在我看来,为了符合数据库设计/整洁数据的原则,OP应该像这样拥有一个类似于events的表。结果如下:
> sample.data[ order(Group, start.date) ]

    start.date Group   end.date
 1: 2010-01-01     A 2011-01-01
 2: 2010-01-01     A 2011-01-01
 3: 2011-01-01     A 2012-01-01
 4: 2011-01-01     A 2012-01-01
 5: 2012-01-01     A 2013-01-01
 6: 2012-01-01     A 2013-01-01
 7: 2013-01-01     A 2014-01-01
 8: 2013-01-01     A 2014-01-01
 9: 2014-01-01     A       <NA>
10: 2014-01-01     A       <NA>
11: 2010-04-01     B 2011-04-01
12: 2010-04-01     B 2011-04-01
...

目前我只是指向文档页面,因为关于连接的官方说明尚未发布。 - Frank
太好了,谢谢。还有一个全新的data.table功能需要学习。这是包的新添加吗? - moman822
“on”语法是自1.9.6版本以来的新功能,但是“X[Y, xvar := yvar]”在我使用该软件包的时间内一直存在。对于我的目的来说,这是其中最好的功能之一。 - Frank

3

初步方法

一种选择是利用 dplyr 工作流程:

require(dplyr); require(magrittr)
sample.data %<>%
    group_by(Group) %>% 
    mutate(end.date = sort(start.date, decreasing = FALSE)[2]) %>%

评论

你可以操作sort函数和[n]值来从组内获取第二小、最高或任何其他日期。

替代方法

根据评论中的讨论。

sample.data %<>%
    arrange(Group, start.date) %>%
    group_by(Group) %>%
    mutate(end.date2 = sort(start.date, decreasing = FALSE)[row_number(Group) + 2]) %>% 
    arrange(Group)

预览

    >> head(sample.data, n = 4)
Source: local data frame [4 x 4]
Groups: Group [1]

  start.date Group       V3  end.date2
      <date> <chr>    <dbl>     <date>
1 2010-01-01     A 4.899328 2011-01-01
2 2010-01-01     A 3.451904 2011-01-01
3 2011-01-01     A 5.779825 2012-01-01
4 2011-01-01     A 4.182594 2012-01-01

1
@Frank,谢谢你之前的评论。我同意,我喜欢基于dplyr的工作流程,因为它易读性强,但在R中有很多种方法可以实现。 - Konrad
你的 dplyr 解法和 @Frank 的 data.table 解法都将 end.date 设置为每个 Group 组中的每个观测值相同。请参见我的问题中所期望的输出。 - moman822
@moman822 所以基本上,对于 Group A 中的每个观测值,它应该按照日期的相反顺序提供从第二个最早的日期开始的日期? - Konrad
@Konrad 新的 end.date 应该是 Group 中下一个(时间上向前)的 start.date。我在问题中扩展了我的样例期望输出,这应该能更清楚地说明。 - moman822
你的“替代方法”回答了我的问题,但“初始方法”没有。 - moman822

2

1) 按照Group分组,对于当前组中的每个start.date元素,在sort(unique(start.date))中找到其位置,并返回下一个位置处的值:

sample.data[, end.date := {u <- sort(unique(start.date)); u[match(start.date, u) + 1]}, 
  by = Group]

2) 使用ave,同样的方法也可以在不使用任何包的情况下工作:

transform(sample.data, end.date = ave(start.date, Group, FUN = 
   function(x) { u <- unique(sort(x)); u[match(x, u) + 1] }))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接