我有几个地点的一些商业活动的开始和结束时间。活动可能会也可能不会在每一天发生,并且活动持续时间不重叠。例如,运行以下命令:
inputdata = data.frame(
location = c('x','x','y','z','z'),
start = c(as.POSIXct("2010/1/1 8:28:00"),as.POSIXct("2010/1/2 7:20:00"),
as.POSIXct("2010/1/1 10:22:00"),
as.POSIXct("2010/1/5 13:28:00"),as.POSIXct("2010/1/7 15:39:00")),
end = c(as.POSIXct("2010/1/1 13:25:00"),as.POSIXct("2010/1/2 10:09:00"),
as.POSIXct("2010/1/1 15:24:00"),
as.POSIXct("2010/1/6 00:28:00"),as.POSIXct("2010/1/7 19:34:00"))
)
输入数据看起来像:
location start end
1 x 2010-01-01 08:28:00 2010-01-01 13:25:00
2 x 2010-01-02 07:20:00 2010-01-02 10:09:00
3 y 2010-01-01 10:22:00 2010-01-01 15:24:00
4 z 2010-01-05 13:28:00 2010-01-06 00:28:00
5 z 2010-01-07 15:39:00 2010-01-07 19:34:00
我想构建一个每小时一次的数据集,其中有三列:1.location、2.hour和3.indicator,每行对应一对location和sharp hour(例如,as.POSIXct("2010/1/1 13:00:00")
),其中indicator是一个伪值,如果这个小时介于该位置的一些事件开始和结束时间之间,则为1。例如,假设输出的每小时数据为2010-01-01到2010-01-07。运行此:
output = data.frame(
location = rep(c('x','y','z'),
each=length(seq(as.POSIXct("2010/1/1"), as.POSIXct("2010/1/7 23:00:00"), "hours"))),
hour = rep(seq(as.POSIXct("2010/1/1"), as.POSIXct("2010/1/7 23:00:00"), "hours"),3),
indicator = rep(0,3*length(seq(as.POSIXct("2010/1/1"), as.POSIXct("2010/1/7 23:00:00"), "hours"))))
所以我们得到的前六行是这样的:
location hour indicator
1 x 2010-01-01 00:00:00 0
2 x 2010-01-01 01:00:00 0
3 x 2010-01-01 02:00:00 0
4 x 2010-01-01 03:00:00 0
5 x 2010-01-01 04:00:00 0
6 x 2010-01-01 05:00:00 0
现在,如果同一行中的小时对同一行的位置有一个有效的事件,我们需要将指示符的值更改为1。例如,由于地点x在2010/1/1上午8:28到2010/1/1下午13:25之间有一个事件。所以早上7点到下午14点的排应该是这样的:
location hour indicator
8 x 2010-01-01 07:00:00 0
9 x 2010-01-01 08:00:00 1
10 x 2010-01-01 09:00:00 1
11 x 2010-01-01 10:00:00 1
12 x 2010-01-01 11:00:00 1
13 x 2010-01-01 12:00:00 1
14 x 2010-01-01 13:00:00 1
15 x 2010-01-01 14:00:00 0
我似乎可以彻底搜索每一对位置和时间,并更新指示符的值,即时间介于该位置某个事件的开始和结束时间之间。但我怀疑这是最好的方式。
或者我在想,我可以首先将输入数据转换为小时数据,只有在开始和结束时间之间,小时才会出现。换句话说,转换后的数据应该看起来像:
location hour indicator
1 x 2010-01-01 08:00:00 1
2 x 2010-01-01 09:00:00 1
3 x 2010-01-01 10:00:00 1
4 x 2010-01-01 11:00:00 1
5 x 2010-01-01 12:00:00 1
6 x 2010-01-01 13:00:00 1
7 x 2010-01-02 07:00:00 1
8 x 2010-01-02 08:00:00 1
9 x 2010-01-02 09:00:00 1
10 x 2010-01-02 10:00:00 1
11 y 2010-01-01 10:00:00 1
12 y 2010-01-01 11:00:00 1
然后我从那里得到每个位置每小时的正确指标。不过,我不知道如何将开始/结束时间转换为每小时的观测值。
到目前为止,这就是我对这个问题的全部理解。
话虽如此,但我没有解决方案,我想寻求帮助。
此外,我想要的只是具有三列的输出。在贡献时,请不要被我的想法所束缚,这可能是无效的。
值得一提的是,实际问题涉及5年,共有30个地点。因此,该算法需要高效。
这里有一种通过交叉连接实现这一点的方法。
library(dplyr)
hours =
data_frame(hour = seq(as.POSIXct("2010/1/1"),
as.POSIXct("2010/1/7 23:00:00"),
"hours") ) %>%
merge(inputdata %>% select(location) %>% distinct)
hours %>%
left_join(inputdata) %>%
filter(start <= hour & hour <= end) %>%
right_join(hours) %>%
mutate(indicator = +!is.na(start))