根据排序和分组添加列

时间:2016-09-26 23:24:08

标签: r dplyr

我有这个数据框

dat = data.frame(ID= c(1,1,1,2,3,3),
              NumberInSequence= c(1,2,3,1,1,2),
              StartTime = as.POSIXct(c("2016-01-01 05:52:05 GMT","2016-01-01 05:52:11 GMT","2016-01-01 05:52:16 GMT","2016-01-01 05:40:05 GMT","2016-01-01 06:12:13 GMT","2016-01-01 07:12:26 GMT"))  ,
              EndTime = as.POSIXct(c("2016-01-01 05:52:10 GMT","2016-01-01 05:52:16 GMT","2016-01-01 05:52:30 GMT","2016-01-01 05:46:05 GMT","2016-01-01 06:12:25 GMT","2016-01-01 08:00:00 GMT")  )
               )


dat

  ID NumberInSequence           StartTime             EndTime
1  1                1 2016-01-01 05:52:05 2016-01-01 05:52:10
2  1                2 2016-01-01 05:52:11 2016-01-01 05:52:16
3  1                3 2016-01-01 05:52:16 2016-01-01 05:52:30
4  2                1 2016-01-01 05:40:05 2016-01-01 05:46:05
5  3                1 2016-01-01 06:12:13 2016-01-01 06:12:25
6  3                2 2016-01-01 07:12:26 2016-01-01 08:00:00

每个ID可以包含1行或更多行,每行ID按时间顺序排列。我想添加2列:

第1栏:"持续时间"以秒为单位,将ID的EndTime与相同id的下一个开始时间之间的时间长度。

第二栏:"下一个开始时间"这是相同ID的实际下一个开始时间。

所以结果应如下所示:

dat $ Duration =?

dat $ NextStartTime =?

  ID NumberInSequence           StartTime             EndTime   Duration    NextStartTime
1  1                1 2016-01-01 05:52:05 2016-01-01 05:52:10     1     2016-01-01 05:52:11
2  1                2 2016-01-01 05:52:11 2016-01-01 05:52:16     0     2016-01-01 05:52:16
3  1                3 2016-01-01 05:52:16 2016-01-01 05:52:30     NA     NA
4  2                1 2016-01-01 05:40:05 2016-01-01 05:46:05     NA     NA
5  3                1 2016-01-01 06:12:13 2016-01-01 06:12:25     3601    2016-01-01 07:12:26
6  3                2 2016-01-01 07:12:26 2016-01-01 08:00:00     NA     NA

例如,对于ID = 3,NUMBER IN SEQUENCE = 1结束时间为61秒,因此持续时间为61,下一个开始时间为ID = 3的07:12:26和序列中的数字= 2。 / p>

对于没有下一个开始时间的行,NA应该显示为ID = 2,序列中的数字= 1。

我正在考虑用dplyr做某事......

########更新

lead()就是答案,但是存在一个小问题。请看这篇文章

using dplyr lead but with some contraints

1 个答案:

答案 0 :(得分:1)

对于NextStartTime,只要您的数据有序(如果不确定则使用arrange(ID, NumberInSequence)),您可以使用dplyr::lead,就像时间序列中的stats::lag一样负滞后。

对于Duration,您可以减去时间,但如果单位可以处于不同的单位,则直接使用difftime会更安全,因此您可以保持一致的单位。

所有在一起:

library(dplyr)

dat %>% group_by(ID) %>% 
    arrange(ID, NumberInSequence) %>%    # not necessary if already arranged, as here
    mutate(NextStartTime = lead(StartTime), 
           Duration = difftime(NextStartTime, EndTime, units = 's'))

## Source: local data frame [6 x 6]
## Groups: ID [3]
## 
##      ID NumberInSequence           StartTime             EndTime       NextStartTime  Duration
##   <dbl>            <dbl>              <dttm>              <dttm>              <dttm>    <time>
## 1     1                1 2016-01-01 05:52:05 2016-01-01 05:52:10 2016-01-01 05:52:11    1 secs
## 2     1                2 2016-01-01 05:52:11 2016-01-01 05:52:16 2016-01-01 05:52:16    0 secs
## 3     1                3 2016-01-01 05:52:16 2016-01-01 05:52:30                <NA>   NA secs
## 4     2                1 2016-01-01 05:40:05 2016-01-01 05:46:05                <NA>   NA secs
## 5     3                1 2016-01-01 06:12:13 2016-01-01 06:12:25 2016-01-01 07:12:26 3601 secs
## 6     3                2 2016-01-01 07:12:26 2016-01-01 08:00:00                <NA>   NA secs