【问题标题】:data table splitting duration based on dates基于日期的数据表拆分持续时间
【发布时间】:2020-08-11 20:03:23
【问题描述】:

我有一个包含 2 列的数据表。一个用于时间戳,一个用于条件。我试图找出某种情况发生的持续时间。我能够得到持续时间。但如果我的病情在两天内,那么我将得到超过 24 小时的时间。 我需要将其拆分为相应的日期。我正在使用rleid 进行分组,然后我找到了持续时间(max(timestamp) - min(timestamp) 在每个满足条件的组中。然后我终于aggregate 它每天都适合sum)。

             timestamp  condition
    2020-01-01 10:10:13 0
    2020-01-01 10:11:23 1
    2020-01-01 10:14:45 1
    2020-01-01 11:23:02 1
    2020-01-01 11:33:14 1
    2020-01-01 16:10:13 0
    2020-01-01 18:34:12 1
    2020-01-01 20:10:33 1
    2020-01-01 23:04:56 1
    2020-01-02 10:14:45 1
    2020-01-02 11:23:02 1
    2020-01-02 11:33:14 0
    2020-01-02 16:10:13 0

在条件为1 时查找持续时间。 预期输出:

Date            Duration
2020-01-01      05:52:35
2020-01-02      11:23:02

当我进行分组和查找持续时间时我得到了什么:

 Date            Duration
2020-01-01      18:10:41

问题在于分组,因为rleid 正在分组而不考虑日期。实际上如果这种情况连续两天发生,那么它应该限制在第一天的23:59:59,然后从第二天的00:00:00开始。这应该持续任意天数。

我的代码:

fdata = data[, group_id := rleid(condition == 1)][]
out = fdata[(condition == 1),][,.(start = as.Date(min(timestamp)),
         duration = as.numeric(max(timestamp) - min(timestamp),units='mins')),by = .((group_id)][,group_id := NULL]

【问题讨论】:

  • 不抱歉...实际上我是在进行 eval 解析...我复制了此处粘贴的条件...现在我已经更正了
  • 我认为两者都将在同一日期'2020-01-02'
  • 如果超过 23:59:59,我想拆分事件。剩余的应该在第二天而不是开始日
  • 这是转换为 hh:mm:ss 后的最终输出...我最初会以分数形式获得持续时间
  • 我猜你正在寻找 as.ITime("10:14:45") + as.ITime("01:08:17")# [1] "11:23:02" 其中01:08:17 是“10:14:45”和“11:23:02”之间的区别

标签: r data.table aggregate grouping


【解决方案1】:

这是一个选项:

DT[, g := rleid(id, as.IDate(timestamp), condition)][
    condition==1L, duration := as.numeric(timestamp[.N] - timestamp[1L], units='secs'), g]

unique(DT, by="g")[condition==1L & duration > 0, .(Duration=sum(duration)), .(id, date=as.IDate(timestamp))]

替代方法:

DT[, g := rleid(id, as.IDate(timestamp), condition)][
    condition==1L, .(id=id[1L], date=as.IDate(timestamp)[1L],
        dft=as.numeric(timestamp[.N] - timestamp[1L], units='secs')), g][
            dft > 0, .(Duration==sum(dft)), .(id, date)]

输出:

   id       date Duration
1:  1 2020-01-01    21155
2:  1 2020-01-02     4097

数据:

library(data.table)
DT <- fread("id,timestamp,condition
1,2020-01-01 10:10:13,0
1,2020-01-01 10:11:23,1
1,2020-01-01 10:14:45,1
1,2020-01-01 11:23:02,1
1,2020-01-01 11:33:14,1
1,2020-01-01 16:10:13,0
1,2020-01-01 18:34:12,1
1,2020-01-01 20:10:33,1
1,2020-01-01 23:04:56,1
1,2020-01-02 10:14:45,1
1,2020-01-02 11:23:02,1
1,2020-01-02 11:33:14,0
1,2020-01-02 16:10:13,0")
DT[, timestamp := as.POSIXct(timestamp, format="%Y-%m-%d %T")]

【讨论】:

  • 但它应该是这些之间差异的总和:2020-01-01 11:33:142020-01-01 10:11:232020-01-01 23:59:592020-01-01 18:34:12
  • 如果我有除日期以外的多个列,如何聚合?喜欢一些ID
  • 什么是condition==1L
  • 如果我有不同的情况怎么办?像字符串一样的东西?
  • 条件 == 1 和条件 ==1L 有什么区别?
【解决方案2】:

我们可以在“条件”列上使用rleid

library(data.table)
library(lubridate)
out <- setDT(df1)[,  .(Duration = max(timestamp) - min(timestamp)),
        .(Date = as.IDate(timestamp),
    grp = rleid(condition), condition)
     ][as.logical(condition)][, .(Duration = sum(Duration)), .(Date)]

out[, Duration := seconds_to_period(Duration)][]
#       Date   Duration
#1: 2020-01-01 5H 52M 35S
#2: 2020-01-02  1H 8M 17S

数据

df1 <- structure(list(timestamp = structure(c(1577891413, 1577891483, 
    1577891685, 1577895782, 1577896394, 1577913013, 1577921652, 1577927433, 
    1577937896, 1577978085, 1577982182, 1577982794, 1577999413), class = c("POSIXct", 
    "POSIXt"), tzone = ""), condition = c(0L, 1L, 1L, 1L, 1L, 0L, 
    1L, 1L, 1L, 1L, 1L, 0L, 0L)), row.names = c(NA, -13L), class = "data.frame")

【讨论】:

  • 这就是我现在正在做的事情。但我没有得到预期的输出
  • @VictorJohnzon 能否请您在帖子中更新您的代码
  • @VictorJohnzon 在您的帖子中说,您只需按rleid 的条件分组以获得差异,然后您将获得总和。我正在按“日期”和“rleid”进行分组
  • 但它应该是这些之间差异的总和:2020-01-01 11:33:142020-01-01 10:11:232020-01-01 23:59:592020-01-01 18:34:12
  • @VictorJohnzon 我的数据集中没有 23:59:59
猜你喜欢
  • 1970-01-01
  • 2016-05-28
  • 1970-01-01
  • 2015-05-21
  • 2019-05-14
  • 2020-10-02
  • 1970-01-01
  • 2021-09-16
  • 1970-01-01
相关资源
最近更新 更多