【问题标题】:Split time difference into blocks of hours from 0:00 to 23:00将时差拆分为从 0:00 到 23:00 的小时块
【发布时间】:2016-02-16 01:42:35
【问题描述】:

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

               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)。第 2 排从 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 天的数据。

标签: r


【解决方案1】:

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))
}

【讨论】:

  • 非常感谢您的帮助!我已经在每日事件登记册上尝试了解决方案,它只给出了我需要的信息(虽然需要一段时间,但数据量很大)。
  • @Emma 另外,由于您提到评估时间很长:如果更快的性能对您来说是一个大问题,您可能需要查看 data.table,这是一个非常流行的快速计算包以及处理大量数据。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-02-25
  • 2019-12-08
  • 1970-01-01
  • 2015-04-12
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
相关资源
最近更新 更多