以不同时间间隔计算时间戳 - 以跨越午夜的间隔问题
我有一个数据帧(“观察”),其格式为H:M
(“时间”)。在第二个数据帧(“间隔”)中,我的时间范围由“From”和“Till”变量定义,格式也为H:M
。以不同时间间隔计算时间戳 - 以跨越午夜的间隔问题
我想统计每个区间内的观测值的数量。我一直在使用data.table
中的between
,这在包含日期时一直没有任何问题。
但是,现在我只有时间戳,没有日期。这导致在跨越午夜(20:00 - 05:59
)的时间间隔中发生的一些问题。这些时间不计入我尝试过的代码中。
实例下
interval.data <- data.frame(From = c("14:00", "20:00", "06:00"), Till = c("19:59", "05:59", "13:59"), stringsAsFactors = F)
observations <- data.frame(Time = c("14:32", "15:59", "16:32", "21:34", "03:32", "02:00", "00:00", "05:57", "19:32", "01:32", "02:22", "06:00", "07:50"), stringsAsFactors = F)
interval.data
# From Till
# 1: 14:00:00 19:59:00
# 2: 20:00:00 05:59:00 # <- interval including midnight
# 3: 06:00:00 13:59:00
observations
# Time
# 1: 14:32:00
# 2: 15:59:00
# 3: 16:32:00
# 4: 21:34:00 # Row 4-8 & 10-11 falls in 'midnight interval', but are not counted
# 5: 03:32:00 #
# 6: 02:00:00 #
# 7: 00:00:00 #
# 8: 05:57:00 #
# 9: 19:32:00
# 10: 01:32:00 #
# 11: 02:22:00 #
# 12: 06:00:00
# 13: 07:50:00
library(data.table)
library(plyr)
adply(interval.data, 1, function(x, y) sum(y[, 1] %between% c(x[1], x[2])), y = observations)
# From Till V1
# 1 14:00 19:59 4
# 2 20:00 05:59 0 # <- zero counts - wrong!
# 3 06:00 13:59 2
我只是调整了你的代码,以获得期望的结果。希望这可以帮助!
adply(interval.data, 1, function(x, y)
if(x[1] > x[2]) return(sum(y[, 1] %between% c(x[1], 23:59), y[, 1] %between% c(00:00, x[2]))) else return(sum(y[, 1] %between% c(x[1], x[2]))), y = observations)
输出是:
From Till V1
1 14:00 19:59 4
2 20:00 05:59 7
3 06:00 13:59 2
这是完美的。只需引用“23:59”和“00:00”。虽然它的确适用于上面的例子。 – MLEN
一种方法是在data.table
使用非球菌加盟,并与时间字符串工作的辅助函数as.ITime
。
您会遇到跨越午夜的间隔问题,但是,应该只有其中之一。并且,如果您对每个“组”间隔的观察次数感兴趣,则可以将该组视为等同于其他组的“不”。
例如,首先将您data.frame
到data.table
library(data.table)
## set your data.frames as `data.table`
setDT(interval.data)
setDT(observations)
然后使用as.ITime
转换为时间整数表示
## convert time stamps
interval.data[, `:=`(FromMins = as.ITime(From),
TillMins = as.ITime(Till))]
observations[, TimeMins := as.ITime(Time)]
## you could combine this step with the non-equi join directly, but I'm separating it for clarity
您现在可以使用非等距联接找到每次落入的时间间隔。他指出,那些reutrn时报“NA”实际上是那些属于午夜跨度区间内
interval.data[
observations
, on = .(FromMins <= TimeMins, TillMins > TimeMins)
]
# From Till FromMins TillMins Time
# 1: 14:00 19:59 872 872 14:32
# 2: 14:00 19:59 959 959 15.59
# 3: 14:00 19:59 992 992 16:32
# 4: NA NA 1294 1294 21:34
# 5: NA NA 212 212 03:32
# 6: NA NA 120 120 02:00
# 7: NA NA 0 0 00:00
# 8: NA NA 357 357 05:57
# 9: 14:00 19:59 1172 1172 19:32
# 10: NA NA 92 92 01:32
# 11: NA NA 142 142 02:22
# 12: 06:00 13:59 360 360 06:00
# 13: 06:00 13:59 470 470 07:50
然后拿到observatins的数量区间的群体,你刚才.N
每个时间点,归纳其可以只被链接到上述声明
interval.data[
observations
, on = .(FromMins <= TimeMins, TillMins > TimeMins)
][
, .N
, by = .(From, Till)
]
# From Till N
# 1: 14:00 19:59 4
# 2: NA NA 7
# 3: 06:00 13:59 2
凡NA
组对应于跨越午夜
你可以在这里使用'as.ITime',而不是转换为分钟吗? – Henrik
@亨利克 - 当然是啊!我总是在'data.table'中得到'ITime' ...我会更新 – SymbolixAU
的一个结束时那些永远是你的时间间隔,或者这只是一个大一个小例子数据集? – SymbolixAU
更大集合的相同结构 – MLEN
使用'adply'与1的边距类型会使data.table的使用无关紧要。 –