将时差从0:00到23:00分成几小时

时间:2016-02-15 15:56:18

标签: r

我有一个包含以下列的数据框,表示事件的开始和结束时间:

               fh_ini              fh_end
1 2015-12-07 00:00:00   2015-12-07 00:00:00
2 2015-12-07 00:00:00   2015-12-07 09:52:46
3 2015-12-07 09:20:13   2015-12-07 09:20:19
4 2015-12-07 09:20:22   2015-12-07 09:36:38
5 2015-12-07 09:40:49   2015-12-07 09:41:05
6 2015-12-07 09:45:12   2015-12-07 09:46:05

我想将fh_end和fh_ini之间的时差分成每个1小时的块,并计算每个块中的分钟数。

目的是计算所有事件和每个块的总时间(例如,00:00到01:00之间的块等)。

我对R很陌生,我不确定我是否可以使用现有函数实际执行此操作,或者我是否应该编写代码(使用循环?)来执行此操作。

我期待的结果如下(来自Excel)。第二排3:00到4:00之间的差距只有42分钟和37秒。

                                       0:00  1:00  2:00  3:00        4:00
07/12/2015 1:00:00  07/12/2015 3:00:00   0     1     1     0           0
07/12/2015 0:00:00  07/12/2015 3:42:37   1     1     1   0,710277778   0

如果我只有2行,例如,每个块的结果总事件时间(以小时为单位)将是:

0:00  1:00  2:00     3:00      4:00
  1     2      2   0,710277778   0 

我想知道是否将时差分解是创建这个块的关键,但我已经尝试过在24个块中创建1天的因子并以相同的方式分解difftime并且我不知道该怎么做做下一个。无论如何,我不确定是否有任何其他方法可以获得不涉及对difftime进行分解的结果。

帮助将不胜感激!

1 个答案:

答案 0 :(得分:0)

chron包提供了处理日期和时间的实用程序。特别是,您可以使用times函数,该函数将格式为hh:mm:ss的字符串转换为times个对象。可以添加和减去此格式的数据,并使用<>maxmin等功能进行比较。试着玩它来了解一切是如何运作的!

解析数据

您首先要将字符串中的fh_inifh_end列转换为时间对象。我会删除日期,只关注时间:

library(chron)

to_times <- function(vec) {
  str_times <- sapply(strsplit(dtimes, ' '), `[`, 2)
  times(str_times)
}

your_data$fh_ini_times <- to_times(your_data$fh_ini)
your_data$fh_end_times <- to_times(your_data$fh_end)

你的数据已经很方便了,所以我在这里所做的就是在空格上分割你的字符串,将它们分成日期和时间对列表,抓住列表中每个条目的第二个元素,然后转换然后转换从字符串到时间。

检查块

我这样做的方法是编写一个占用开始时间,结束时间和块的函数,并返回重叠量。我在下面写了一个例子 - 为了便于阅读,我在冗长的一面做了一点,并清楚地展示了你可以用times数据类型做些什么。

block_check <- function(range_start, range_end, block_start) {
  start_check <- (range_start < block_start + times("01:00:00"))
  end_check <- (range_end > block_start)
  if (start_check & end_check) {
    o_start <- max(block_start, range_start)
    o_end <- min(block_start + times("01:00:00"), range_end)
    return(o_end - o_start)
  } else {
    return(times("00:00:00"))
  }
}

如果你打破这个功能,我只是(1)检查start_timeend_time定义的范围是否与给定的1小时块重叠,如果它确实返回了多少重叠是

使用此功能后,您可以使用mapply将其应用于数据集中的每个开始/结束时间对,如下所示:

z <- mapply(FUN = block_check, your_data$fh_ini_times, your_data$fh_end_times, 
            MoreArgs = list(block_start = times("01:00:00")))
your_data[,"1:00"] <- times(z)

一次完成所有操作

对于你的24个时间段中的每一个都必须执行上述操作,这是笨拙和无聊的。如果你希望得到想象并一次完成所有事情,而不是分别对每个块,你可以遍历一个块列表。在这里,我使用stringr包创建了一个块开始时间(作为字符串)的向量,然后依次将该函数从之前应用到每个元素(作为时间)(使用时间的字符串版本)命名数据框的结果列。)

library(stringr)
blocks <- str_c(as.character(0:23), ":00:00")
f <- function(block) { 
  z <- mapply(FUN = block_check, your_data$fh_ini_times, your_data$fh_end_times, 
              MoreArgs = list(block_start = block)) 
  times(z)
}
for (block in blocks) {
  your_data[, block] <- f(times(block))
}