R按小时划分间隔
可能很简单,但很难解决,在网上寻找答案,但它们通常与R按小时划分间隔,r,time,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", "
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:00时段有60分钟,第三个在21:00时段有55分钟,最后一个在16:00时段有5分钟
结果应该如下(如果我的基本手册添加错误,请道歉;)
当然,有一种直接的方法可以按分钟分割序列,并按分割/间隔进行计数,但我相信这个问题非常常见,必须有一种直接的方法。我最好也有0值窗口,但如果需要,我可以对它们进行排序这是一个使用
dplyr的解决方案
首先,定义一个助手函数find_slots
,以生成start
和end
之间的所有小时数。接下来计算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))
编辑:使用数据表
(可能更快,但我对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]
库(fasttime)
库(数据表)
x=数据表(开始=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"),
结束=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有一个函数lubridate::interval()
,在这里可能很有用 您是如何获得Q
中的值的?Q是属于某个间隔的分钟数,因此,例如,案例4有5分钟(2017-04-18 16:05:00-2017-04-18 16:10:00),而所有其他案例都没有,因此结果是5Nina,您将如何在此处使用lubridate::interval()?它对于处理间隔非常有用,因此所有条目都可以转换为间隔,但是从那里呢?解决方案在逻辑上似乎是正确的,它在一分钟内就出现了错误(a)*60:二进制运算符的非数值参数有什么想法可以加快它的速度吗?我添加了一个data.table版本,可能更快。谢谢,只是测试,顺便说一句,fasttime操作可以在函数之前安全地移动,我认为在表上应用比在行上应用要快。表的版本要慢近50%——在80k记录(还有一个属性要分组)上,dplyr有210秒和data.table 290秒
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
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]