R以小时为单位划分时间间隔

时间:2017-04-28 20:11:53

标签: r time

可能非常容易但是很努力,在网络上寻找答案,但它们通常与cut和快照相关,而不是与重叠间隔

require(data.table)
x = data.table(start=c("2017-04-18 18:05:00","2017-04-18 18:00:00", 
"2017-04-18 21:05:00", "2017-04-18 16:05:00"), 
               end=c("2017-04-18 19:05:00","2017-04-18 21:30:00",
"2017-04-18 22:00:00", "2017-04-18 16:10:00"))

我们有4个观察,我需要将它分配到相应的每小时窗口。

                 start                 end
1: 2017-04-18 18:05:00 2017-04-18 19:05:00
2: 2017-04-18 18:00:00 2017-04-18 21:30:00
3: 2017-04-18 21:05:00 2017-04-18 22:00:00
4: 2017-04-18 16:05:00 2017-04-18 16:10:00
例如,第一个在18:00槽中有55分钟,在19:00槽中有5分钟,下一个在18:00,19:00,20:00和21分钟在21:00有60分钟,第三个将在21:00有55分钟,最后一个在16:00有5分钟

结果应如下所示(对不起,如果我的基本手册添加错误;)

              interval   Q
1: 2017-04-18 16:00:00 5
2: 2017-04-18 17:00:00 0
3: 2017-04-18 18:00:00 115
4: 2017-04-18 19:00:00 65
5: 2017-04-18 20:00:00 120
6: 2017-04-18 21:00:00  85

当然有一种直接的方法可以按分钟切割系列并按切/间隔执行计数,但我相信这个问题很常见,必须有一个直接的方法。我最好也有0值窗口,但我可以根据需要对它们进行排序

2 个答案:

答案 0 :(得分:3)

这是使用dplyr

的解决方案

首先定义辅助函数find_slots以生成startend之间的所有小时数。接下来计算Q值。

最后,通过对每个插槽进行分组来汇总数据。

library(dplyr)

find_slots <- function(a, b){
    slots = seq(a-minute(a)*60-second(a),
                b-minute(b)*60-second(b),
                "hour")

    dateseq = slots
    dateseq[1] = a
    r = c(dateseq, b)

    d = as.numeric(difftime(r[-1], r[-length(r)], unit = 'min'))

    data.frame(slot = slots, Q = d)
}

x %>%
    rowwise %>%
    do(find_slots(.$start, .$end)) %>%
    ungroup() %>%
    group_by(slot) %>%
    summarize(Q = sum(Q))

结果(缺少17:00的0值):

                 slot   Q
1 2017-04-18 16:00:00   5
2 2017-04-18 18:00:00 115
3 2017-04-18 19:00:00  65
4 2017-04-18 20:00:00  60
5 2017-04-18 21:00:00  85
6 2017-04-18 22:00:00   0

编辑:使用data.table

(可能更快,但我对data.table不太熟悉)

还使用fasttime库加速解析日期时间。

library(fasttime)
library(data.table)

x = data.table(start=c("2017-04-18 18:05:00","2017-04-18 18:00:00", 
"2017-04-18 21:05:00", "2017-04-18 16:05:00"), 
               end=c("2017-04-18 19:05:00","2017-04-18 21:30:00",
"2017-04-18 22:00:00", "2017-04-18 16:10:00"))

find_slots2 <- function(a, b){
    a = fasttime::fastPOSIXct(a)
    b = fasttime::fastPOSIXct(b)
    slots = seq(a-data.table::minute(a)*60-data.table::second(a)*60,
                b-data.table::minute(b)*60-data.table::second(b)*60,
                "hour")

    hourseq = c(a, slots[-1], b)

    d = difftime(hourseq[-1], hourseq[-length(hourseq)], unit = 'min')

    list(slot = slots, Q = d)
}

x[, find_slots2(start, end), by = 1:nrow(x)][order(slot), .(Q = as.numeric(sum(Q))), by = slot]

答案 1 :(得分:0)

Lubridate有一个函数lubridate::interval(),在这里很有用。