【问题标题】:r, update the timestamp based on following record's valuer,根据以下记录的值更新时间戳
【发布时间】:2018-09-15 21:13:14
【问题描述】:

试图以这样的方式操纵timestamp变量:如果下一个activity的开始时间在前一个activity的结束时间之前,那么将前一个activity的开始和结束时间更新为下一个activity的前1秒.

补充说明:

一个活动可以在同一个作品中重复;即活动“A”。

一些单独的活动有相同的开始和结束时间,但有些不同。这是我故意做的;你可以忽略这个。

workID  workActivityID activity     status             timestamp      timestampDesired
     1               1        A      start   2018-01-01 09:55:01   2018-01-01 09:54:05
     1               1        A        end   2018-01-01 09:55:01   2018-01-01 09:54:05
     1               2        B      start   2018-01-01 09:54:06   2018-01-01 09:54:06
     1               2        B        end   2018-01-01 09:56:22   2018-01-01 09:56:22
     1               3        C      start   2018-01-01 09:57:22   2018-01-01 09:57:22
     1               3        C        end   2018-01-01 09:57:22   2018-01-01 09:57:22
     1               4        A      start   2018-02-02 08:35:00   2018-02-02 08:35:00
     1               4        A        end   2018-02-02 08:35:00   2018-02-02 08:35:00
     2               1        A      start   2018-02-02 08:13:55   2018-02-02 08:14:01
     2               1        A        end   2018-02-02 08:14:20   2018-02-02 08:14:01
     2               2        B      start   2018-02-02 08:14:02   2018-02-02 08:14:02
     2               2        B        end   2018-02-02 08:14:50   2018-02-02 08:14:50
     2               3        C      start   2018-02-02 10:00:00   2018-02-02 10:00:00
     2               3        C        end   2018-02-02 10:00:00   2018-02-02 10:00:00
     2               4        A      start   2018-02-02 10:22:00   2018-02-02 10:22:00
     2               4        A        end   2018-02-02 10:24:00   2018-02-02 10:24:00

数据:

library(lubridate)
df <- 
  data.frame(
    workID = rep(c(1,2), each=8),
    workActivityID = rep(c(1,2,3,4), each=2, times=2),
    activity = rep(c("A","B","C","A"), each=2, times=2),
    startEnd = rep(c("start", "end"), times=8),
    timestamp = ymd_hms(c("2018-01-01 09:55:01", "2018-01-01 09:55:01", "2018-01-01 09:54:06", "2018-01-01 09:56:22", "2018-01-01 09:57:22", "2018-01-01 09:57:22", "2018-02-02 08:35:00","2018-02-02 08:35:00",
                          "2018-02-02 08:13:55", "2018-02-02 08:14:20", "2018-02-02 08:14:02", "2018-02-02 08:14:50", "2018-02-02 10:00:00", "2018-02-02 10:00:00", "2018-02-02 10:22:00", "2018-02-02 10:24:00")),
    timestampDesired = ymd_hms(c("2018-01-01 09:54:05", "2018-01-01 09:54:05", "2018-01-01 09:54:06", "2018-01-01 09:56:22", "2018-01-01 09:57:22", "2018-01-01 09:57:22", "2018-02-02 08:35:00", "2018-02-02 08:35:00",
                                 "2018-02-02 08:14:01", "2018-02-02 08:14:01", "2018-02-02 08:14:02", "2018-02-02 08:14:50", "2018-02-02 10:00:00", "2018-02-02 10:00:00", "2018-02-02 10:22:00", "2018-02-02 10:24:00")))

【问题讨论】:

    标签: r timestamp


    【解决方案1】:

    可以使用tidyr::spreadtidyr::gather 找到可能的解决方案。该方法很简单,因为将startend 移动到同一行,这样决策和更改操作(如果需要)会更容易。执行修改后,将其更改回长格式。

    library(tidyverse)
    
    df %>% select(-timestampDesired) %>%
      spread(startEnd, timestamp) %>%
      group_by(workID) %>%
      mutate(start = as.POSIXct(ifelse(!is.na(lead(start)) & lead(start) < end,
                      lead(start) - 1, start), origin = "1970-01-01 00:00:00" )) %>%
      mutate(end = as.POSIXct(ifelse(!is.na(lead(start)) & lead(start) < end,
                     lead(start)  - 1, end), origin = "1970-01-01 00:00:00" )) %>%
      ungroup() %>%  
      gather("startEnd", "timestamp", c("start","end")) %>%
      arrange(workID, workActivityID, desc(startEnd)) %>%
      as.data.frame()
    
    #      workID workActivityID activity startEnd           timestamp
    # 1       1              1        A    start 2018-01-01 09:54:05
    # 2       1              1        A      end 2018-01-01 09:54:05
    # 3       1              2        B    start 2018-01-01 09:54:06
    # 4       1              2        B      end 2018-01-01 09:56:22
    # 5       1              3        C    start 2018-01-01 09:57:22
    # 6       1              3        C      end 2018-01-01 09:57:22
    # 7       1              4        A    start 2018-02-02 08:35:00
    # 8       1              4        A      end 2018-02-02 08:35:00
    # 9       2              1        A    start 2018-02-02 08:14:01
    # 10      2              1        A      end 2018-02-02 08:14:01
    # 11      2              2        B    start 2018-02-02 08:14:02
    # 12      2              2        B      end 2018-02-02 08:14:50
    # 13      2              3        C    start 2018-02-02 10:00:00
    # 14      2              3        C      end 2018-02-02 10:00:00
    # 15      2              4        A    start 2018-02-02 10:22:00
    # 16      2              4        A      end 2018-02-02 10:24:00
    

    【讨论】:

    • 感谢您的解决方案,效果很好!如果您能简要解释该部分的逻辑,我将不胜感激: as.POSIXct(ifelse(!is.na(lead(start)) & lead(start)
    • 检查当前行的end时间和下一行的start时间。如果开始时间小于 1 秒,则减去。 lead 为您提供下一行的数据。最后在操作时间改为双格式后。我不得不将它改回 POSIXct 格式。
    【解决方案2】:

    只是发布一个 data.table 解决方案。内联解释

    #cast into a wide format
    wideDT <- dcast.data.table(DT, ... ~ startEnd, value.var="timestamp")
    
    #lead the start time vector and compare start time and amend start and end time if required
    wideDT[, c("newstart", "newend") := {
            x <- shift(start, type="lead", fill=max(end))
            list(newstart=as.POSIXct(ifelse(x < end, x - 1, start), origin="1970-01-01"),
                newend=as.POSIXct(ifelse(x < end, x - 1, end), origin="1970-01-01"))
        }, by=.(workID)]
    
    #get OP's desired output
    wideDT[.(workID, workActivityID, activity), 
        list(startend=c("start", "end"), 
            timestamp=c(start, end),
            timestampDesired=c(newstart, newend)), by=.EACHI]
    

    数据:

    library(data.table)
    DT <- data.table(
        workID = rep(c(1,2), each=8),
        workActivityID = rep(c(1,2,3,4), each=2, times=2),
        activity = rep(c("A","B","C","A"), each=2, times=2),
        startEnd = rep(c("start", "end"), times=8),
        timestamp = as.POSIXct(c("2018-01-01 09:55:01", "2018-01-01 09:55:01", "2018-01-01 09:54:06", "2018-01-01 09:56:22", "2018-01-01 09:57:22", "2018-01-01 09:57:22", "2018-02-02 08:35:00","2018-02-02 08:35:00",
            "2018-02-02 08:13:55", "2018-02-02 08:14:20", "2018-02-02 08:14:02", "2018-02-02 08:14:50", "2018-02-02 10:00:00", "2018-02-02 10:00:00", "2018-02-02 10:22:00", "2018-02-02 10:24:00")))
    

    【讨论】:

    • 也谢谢您!这对于较大的表很有用。
    • 原始数据集中有 15 列。与其将列名单独写成 .(workID, workActivityID, activity),我们可以自动包含它们吗?
    • 是的,您可以使用 DT[,-c(“start”,”end”,”newstart”,”newend”)] 代替 .(blah blah blah)。不在电脑前
    猜你喜欢
    • 2020-07-30
    • 1970-01-01
    • 2013-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-07-31
    • 1970-01-01
    • 2019-02-02
    • 1970-01-01
    相关资源
    最近更新 更多