如何使用定期拆分的时间数据重组数据帧(并计算更新的持续时间)

How to restructure a data frame with time data split at regular interval (and compute updated durations)

我有如下数据框:

tab <- data.frame(Behav = c("Rest","Eat","Eat"),      
              Behav.start= c("14:10:40","14:13:25","17:35:00"),
              Behav.end = c("14:13:24","17:31:05","17:37:25"), 
              Behav.dur.s = c("164","19060","145"))

Behav    Behav.start    Behav.end    Behav.dur.s
 Rest     14:10:40       14:13:24      164
 Eat      14:13:25       17:31:05      11860
 Eat      17:35:00       17:37:25      145       

N.B。 'Behav.dur.s' = 'Behav.start' 和 'Behav.end'

之间的时间间隔(以秒为单位)

我想计算一个小时的时间预算,换句话说,我想计算一个人在每个 1 小时的时间间隔内花费了多长时间休息、吃饭等。

然后,我尝试(但失败了..)重组我的初始数据框选项卡以获得新的数据框,例如行为持续一个多小时的行 (Behav.dur.s > 3600) 是用持续 1 小时间隔的给定行为替换为 n 'duplicated' 行,更新 Behav.start、Behav.end 和 Behav.dur.s

Behav    Behav.start    Behav.end    Behav.dur.s
 Rest     14:10:40       14:13:24      164
 Eat      14:13:25       15:00:00      2795
 Eat      15:00:00       16:00:00      3600
 Eat      16:00:00       17:00:00      3600
 Eat      17:00:00       17:31:05      1865
 Eat      17:35:00       17:37:25      145 

然后,我就能计算出每小时的时间预算。

非常感谢您的帮助,非常感谢!

在以下假设下考虑以下步骤,即在一天中的所有 24 小时内使用交叉联接,然后子集到特定持续时间,最后重新计算 start/end 点。

假设

  • 时间源自发布的 HH:MM 字符串格式;
  • 时间范围仅在 一天内(即一天中 00:0023:59 午夜的时间)。否则按天拆分和 rbind 一起;
  • tab 中的数据大小合理,因为交叉连接将为选项卡的 每个 行添加(在子集之前)24 行。

步骤

  1. 数据Build/Conversion

    # CONVERT TIMES TO POSIXct TYPES
    tab <- within(tab, {
      Behav.start = as.POSIXct(Behav.start, tz="GMT", format="%H:%M:%S")
      Behav.end = as.POSIXct(Behav.end, tz="GMT", format="%H:%M:%S")
    })
    
    # BUILD DF OF ALL 24 HOURS DURATIONS FOR CURRENT DATE
    hours_df <- data.frame(start_hour = as.POSIXlt(as.POSIXct(Sys.Date()) + c(0:23)*60*60),
                           end_hour = as.POSIXlt(as.POSIXct(Sys.Date()) + c(1:24)*60*60))
    
  2. 交叉连接 + 子集

    mdf <- merge(tab, hours_df, all=TRUE)
    
    sdf <- subset(mdf, Behav.start <= end_hour & Behav.end >= start_hour)  
    
  3. 计算最终结果Start/End

    final_df <- within(sdf, {
      final_start <- as.POSIXct(ifelse(Behav.start > start_hour, Behav.start, start_hour),
                                tz="GMT", origin="1970-01-01")
      final_end <- as.POSIXct(ifelse(Behav.end < end_hour, Behav.end, end_hour),
                              tz="GMT", origin="1970-01-01")
    
      final_dur <- as.numeric(difftime(final_end, final_start, units="secs"))
    
      rm(Behav.start, Behav.end, start_hour, end_hour, Behav.dur.s)
    
    })[c("Behav", "final_start", "final_end", "final_dur")]
    
    # CONVERT DATE/TIME TO STRING TIME
    final_df <- data.frame(within(final_df, {
       final_start <- format(final_start, format="%H:%M:%S")
       final_end <- format(final_end, format="%H:%M:%S")
    }), row.names = NULL)
    
    final_df
    #   Behav final_start final_end final_dur
    # 1  Rest    14:10:40  14:13:24       164
    # 2   Eat    14:13:25  15:00:00      2795
    # 3   Eat    15:00:00  16:00:00      3600
    # 4   Eat    16:00:00  17:00:00      3600
    # 5   Eat    17:00:00  17:31:05      1865
    # 6   Eat    17:35:00  17:37:25       145