如何找到两者之间的累计时间

时间:2017-11-13 11:44:09

标签: r dplyr data.table

我有两个数据表如下:

DT1

  id            start_time             end_time
 604        2017-08-10 18:44:14    2017-08-11 19:33:17
 604        2017-08-10 20:38:20    2017-08-11 20:44:44
 604        2017-08-10 20:54:26    2017-08-11 20:58:48
 604        2017-08-10 21:35:50    2017-08-11 22:03:14
 604        2017-08-10 22:05:42    2017-08-11 22:17:12

.......

DT2

 id             t1                            t2
 604        2017-08-10 18:40:14    2017-08-11 18:44:14
 604        2017-08-10 18:44:14    2017-08-11 18:47:14
 604        2017-08-10 19:44:14    2017-08-11 19:47:14
 604        2017-08-10 20:30:14    2017-08-11 20:42:20
 604        2017-08-10 21:44:14    2017-08-11 21:49:14
 604        2017-08-10 22:44:14    2017-08-11 22:48:14

...

从这两个中我想确定DT2行的累积位于DT的范围之间!例如,第1行从2017-08-10 18:44:14 to 2017-08-11 19:33:17开始所以我想在那段时间内在DT中积累时间并在DT1中作为eah行的列附加 例如,第一行就像

   id            start_time             end_time           durationFromDT2
   604        2017-08-10 18:44:14    2017-08-11 19:33:17       420
   604        2017-08-10 20:38:20    2017-08-11 20:44:44       240

420是因为(2017-08-11 18:44:14-2017-08-10 18:40:14)+(2017-08-11 18:47:14-2017-08-10 18:44:14)。如果DT2在这段时间内没有出现,那么我希望它为0.同样明智的我也必须按照许多id分组。

240因为时间是(2017-08-11 20:42:20-2017-08-10 20:38:20)

所以它基本上是DT1在DT1时间段内的覆盖范围 我尝试在行中循环但是没有顺利。相反,我正在寻找任何 dplyr 数据表解决方案。因为循环不能正常工作

感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

假设评论中建议的纠正措施是正确的,请在下面找到dplyr解决方案:

merge(DT1, DT2, by = "id", all = TRUE) %>%
    filter(t2 >= start_time, t1 <= end_time) %>% 
    mutate(t1_adj = if_else(start_time > t1, start_time, t1),
           t2_adj = if_else(end_time < t2, end_time, t2),
           difftime = difftime(t2_adj, t1_adj, units = "secs")) %>% 
    group_by(id, start_time, end_time) %>% 
    summarize(durationFromDT2 = sum(difftime)) %>% 
    right_join(DT1) %>% 
    mutate(durationFromDT2 = coalesce(durationFromDT2, 0))
  • cross join每个表之间的所有记录

  • filter向下cross join只包含DT2 DT1区间内的时间点

  • mutate _adj使用了列来强制t1t2次在DT1开始和结束时间点之间保持约束,然后计算时间间隔。

  • groupsummarize DT1条记录的持续时间。

  • 要列出最终结果中的所有NULL条记录,请再次right_join DT1表格。

  • Replace NA s为0。

结果如下:

# A tibble: 5 x 4
# Groups:   id, start_time [5]
     id          start_time            end_time durationFromDT2
  <int>              <dttm>              <dttm>          <time>
1   604 2017-08-10 18:44:14 2017-08-10 19:33:17        180 secs
2   604 2017-08-10 20:38:20 2017-08-10 20:44:44        240 secs
3   604 2017-08-10 20:54:26 2017-08-10 20:58:48          0 secs
4   604 2017-08-10 21:35:50 2017-08-10 22:03:14        300 secs
5   604 2017-08-10 22:05:42 2017-08-10 22:17:12          0 secs

来自OP的可重现(整流)样本数据帧如下:

library(lubridate)
DT1 <- 
    read.table(text = "
                        id         start_date start_time  end_date   end_time
                        604        2017-08-10 18:44:14    2017-08-10 19:33:17
                        604        2017-08-10 20:38:20    2017-08-10 20:44:44
                        604        2017-08-10 20:54:26    2017-08-10 20:58:48
                        604        2017-08-10 21:35:50    2017-08-10 22:03:14
                        604        2017-08-10 22:05:42    2017-08-10 22:17:12
                      ", header = TRUE, stringsAsFactors = FALSE) %>% 
    mutate(start_time = ymd_hms(paste(start_date, start_time)),
           end_time   = ymd_hms(paste(end_date, end_time))) %>% 
    select(-c(start_date, end_date))

DT2 <- 
    read.table(text = "
                         id         d1         t1          d2         t2
                         604        2017-08-10 18:40:14    2017-08-10 18:44:14
                         604        2017-08-10 18:44:14    2017-08-10 18:47:14
                         604        2017-08-10 19:44:14    2017-08-10 19:47:14
                         604        2017-08-10 20:30:14    2017-08-10 20:42:20
                         604        2017-08-10 21:44:14    2017-08-10 21:49:14
                         604        2017-08-10 22:44:14    2017-08-10 22:48:14
                      ", header = TRUE, stringsAsFactors = FALSE) %>% 
    mutate(t1 = ymd_hms(paste(d1,t1)),
           t2 = ymd_hms(paste(d2,t2)),
           ) %>% 
    select(-c(d1, d2))