【问题标题】:Duplicating and modifying rows based on datetime基于日期时间复制和修改行
【发布时间】:2020-09-14 17:09:20
【问题描述】:

我有一个看起来像这样的 data.table

library(dplyr)
library(data.table)

dt <- data.table(ID=c("A001","A002","A003","A004"),start_time=c('2019-06-18 05:18:00','2020-03-04 05:00:00',
                 '2019-05-10 19:00:00','2020-01-06 22:42:00'),end_time=c('2019-06-18 08:41:00','2020-03-04 05:04:00',
                 '2019-05-10 19:08:00','2020-01-07 03:10:00'))
 ID      

    start_time            end_time duration
1: A001 2019-06-18 05:18:00 2019-06-18 08:41:00 203 mins
2: A002 2020-03-04 05:59:00 2020-03-04 06:04:00   5 mins
3: A003 2019-05-10 19:00:00 2019-05-10 19:08:00   8 mins
4: A004 2020-01-06 22:42:00 2020-01-07 03:10:00 268 mins

持续时间被简单地计算为

dt$start_time <- as.POSIXct(dt$start_time, tz='UTC')  
dt$end_time <- as.POSIXct(dt$end_time, tz='UTC')
dt <- dt %>% mutate(duration = (end_time-start_time))

我需要复制持续时间大于从 start_time 开始的小时结束的行(涵盖 > 1 小时的记录)。我需要为他们更改开始时间(小时开始),结束时间 - 小时结束或原始结束时间,如果是最后一行(最后查看时间),以及相应的持续时间,以便最终输出看起来像:

    dt_expected <- data.table(ID=c("A001","A001","A001","A001","A002","A002","A003","A004","A004","A004","A004","A004","A004"),
start_time=c('2019-06-18 05:18:00','2019-06-18 06:00:00','2019-06-18 07:00:00','2019-06-18 08:00:00', '2020-03-04 05:59:00', '2020-03-04 06:00:00',  '2019-05-10 19:00:00',
'2020-01-06 22:42:00', '2020-01-06 23:00:00','2020-01-07 00:00:00','2020-01-07 01:00:00','2020-01-07 02:00:00','2020-01-07 03:00:00'),
end_time=c('2019-06-18 05:59:00','2019-06-18 06:59:00','2019-06-18 07:59:00','2019-06-18 08:41:00','2020-03-04 05:59:00','2020-03-04 06:04:00',   '2019-05-10 19:08:00',    '2020-01-06 22:59:00','2020-01-06 23:59:00','2020-01-07 00:59:00','2020-01-07 01:59:00', '2020-01-07 02:59:00','2020-01-07 03:10:00'), 
duration = c(12,60,60,41,1,4,8,18,60,60,60,60,10)) 

请注意,ID A002 的记录也应该重复,因为持续时间发生在 2 个不同的小时内。

      ID          start_time            end_time duration
 1: A001 2019-06-18 05:18:00 2019-06-18 05:59:00       12
 2: A001 2019-06-18 06:00:00 2019-06-18 06:59:00       60
 3: A001 2019-06-18 07:00:00 2019-06-18 07:59:00       60
 4: A001 2019-06-18 08:00:00 2019-06-18 08:41:00       41
 5: A002 2020-03-04 05:59:00 2020-03-04 05:59:00        1
 6: A002 2020-03-04 06:00:00 2020-03-04 06:04:00        4
 7: A003 2019-05-10 19:00:00 2019-05-10 19:08:00        8
 8: A004 2020-01-06 22:42:00 2020-01-06 22:59:00       18
 9: A004 2020-01-06 23:00:00 2020-01-06 23:59:00       60
10: A004 2020-01-07 00:00:00 2020-01-07 00:59:00       60
11: A004 2020-01-07 01:00:00 2020-01-07 01:59:00       60
12: A004 2020-01-07 02:00:00 2020-01-07 02:59:00       60
13: A004 2020-01-07 03:00:00 2020-01-07 03:10:00       10

【问题讨论】:

    标签: r datetime duplicates row rbind


    【解决方案1】:

    我认为这与您正在寻找的内容非常接近。

    这会创建新的开始和结束时间行,每小时使用来自purrrmap 一行。

    然后,对于每个ID,它将使用pmin 确定start_timeend_time

    首先,对于end_time,它取该行的end_time 和比该行的start_time 晚一个小时之间的最小值。例如,A001 的第一行将具有 6:00 的 end_time,这是 5:18 到最接近的小时的 ceiling_date 时间,并且从 map 生成的序列中小于 6:18。对于 A001 的最后一行,end_time 是 8:41,小于 ceiling_date 时间 9:00。

    start_time 将采用最后一行的end_time 和该行的start_time 之间的最小值。例如,A001 的第二行将有 6:00,也就是上面那行的end_time,与map 生成的序列相比,它小于 6:18。

    请注意,duration 的一行有 0 分钟 - 时间正好是整点 (19:00:00)。这些可以被过滤掉。

    library(purrr)
    library(dplyr)
    library(tidyr)
    library(lubridate)
    
    dt %>%
      rowwise() %>%
      mutate(start_time = map(start_time, ~seq.POSIXt(., ceiling_date(end_time, "hour"), by = "hour"))) %>%
      unnest(start_time) %>%
      group_by(ID) %>%
      mutate(end_time = pmin(ceiling_date(start_time, unit = "hour"), end_time),
             start_time = pmin(floor_date(lag(end_time, default = first(end_time)), unit = "hour"), start_time),
             duration = difftime(end_time, start_time, units = "mins"))
    

    输出

       ID    start_time          end_time            duration
       <chr> <dttm>              <dttm>              <drtn>  
     1 A001  2019-06-18 05:18:00 2019-06-18 06:00:00 42 mins 
     2 A001  2019-06-18 06:00:00 2019-06-18 07:00:00 60 mins 
     3 A001  2019-06-18 07:00:00 2019-06-18 08:00:00 60 mins 
     4 A001  2019-06-18 08:00:00 2019-06-18 08:41:00 41 mins 
     5 A002  2020-03-04 05:59:00 2020-03-04 06:00:00  1 mins 
     6 A002  2020-03-04 06:00:00 2020-03-04 06:04:00  4 mins 
     7 A003  2019-05-10 19:00:00 2019-05-10 19:00:00  0 mins 
     8 A003  2019-05-10 19:00:00 2019-05-10 19:08:00  8 mins 
     9 A004  2020-01-06 22:42:00 2020-01-06 23:00:00 18 mins 
    10 A004  2020-01-06 23:00:00 2020-01-07 00:00:00 60 mins 
    11 A004  2020-01-07 00:00:00 2020-01-07 01:00:00 60 mins 
    12 A004  2020-01-07 01:00:00 2020-01-07 02:00:00 60 mins 
    13 A004  2020-01-07 02:00:00 2020-01-07 03:00:00 60 mins 
    14 A004  2020-01-07 03:00:00 2020-01-07 03:10:00 10 mins 
    

    【讨论】:

      猜你喜欢
      • 2013-02-05
      • 2016-07-26
      • 2013-04-24
      • 2021-08-14
      • 2021-12-11
      • 2013-08-03
      • 1970-01-01
      • 1970-01-01
      • 2023-03-08
      相关资源
      最近更新 更多