合并日期和小时范围 [英] Merge on date and hour range

查看:115
本文介绍了合并日期和小时范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个日期时间的数据框,就像这样:

I have a dataframe of datetimes, like so:

library(lubridate)

date_seq <- seq.POSIXt(ymd_hm('2016-04-01 0:00'), ymd_hm('2016-04-30 23:30'), by = '30 mins')
datetimes <- data.frame(datetime = date_seq)

我还得到了一个数据框,其中包含打开时间,该时间指定了在该日期范围内的几天中的适用于打开时间的天数以及一个小时范围内的商店,如:

I've also got a dataframe containing opening times that specify a range of days over which the opening times apply and an hour range over which the store is open for the days in the date range, like so:

opening_times <- data.frame(from_date = c('2016-03-01', '2016-04-15'),
                            till_date = c('2016-04-15', '2016-05-20'),
                            from_time = c('11:00', '10:30'),
                            till_time = c('22:00', '23:00'))

我想在datetimes中标记开放时间之内的行.也就是说,只要行中的日期时间在from_datetill_date以及from_timetill_time内,我都希望列为TRUE.

What I would like is to mark in datetimes those rows which are inside the opening hours. That is, I want a column that is TRUE whenever the datetime in the row is within both from_date and till_date and within from_time and till_time.

推荐答案

lubridate具有%within%函数,用于检查时间是否在lubridate::interval之内,一旦创建间隔向量,此操作就很容易:

lubridate has a %within% function for checking whether a time is within a lubridate::interval which can make this easy once you create a vector of intervals:

# make a sequence of days in each set from opening_times
open_intervals <- apply(opening_times, 1, function(x){
    dates <- seq.Date(ymd(x[1]), ymd(x[2]), by = 'day')
})

# turn each date into a lubridate::interval object with the appropriate times
open_intervals <- mapply(function(dates, from, to){
    interval(ymd_hm(paste(dates, from)), ymd_hm(paste(dates, to)))
}, open_intervals, opening_times$from_time, opening_times$till_time)

# combine list items into one vector of intervals
open_intervals <- do.call(c, open_intervals)

# use lubridate::%within% to check if each datetime is in any open interval
datetimes$open <- sapply(datetimes$datetime, function(x){
    any(x %within% open_intervals)
})

datetimes[20:26,]
#               datetime  open
# 20 2016-04-01 09:30:00 FALSE
# 21 2016-04-01 10:00:00 FALSE
# 22 2016-04-01 10:30:00 FALSE
# 23 2016-04-01 11:00:00  TRUE
# 24 2016-04-01 11:30:00  TRUE
# 25 2016-04-01 12:00:00  TRUE
# 26 2016-04-01 12:30:00  TRUE


编辑

如果您恰好有两个小时的时间,则可以将整个内容压缩为一个(有点大)的ifelse:


Edit

If you have exactly two sets of hours, you can condense the whole thing into a (somewhat huge) ifelse:

datetimes$open <- ifelse(as.Date(datetimes$datetime) %within% 
                             interval(opening_times$from_date[1], 
                                      opening_times$till_date[1]), 
                         hm(format(datetimes$datetime, '%H:%M')) >= hm(opening_times$from_time)[1] &
                             hm(format(datetimes$datetime, '%H:%M')) <= hm(opening_times$till_time)[1],
                         hm(format(datetimes$datetime, '%H:%M')) >= hm(opening_times$from_time)[2] &
                             hm(format(datetimes$datetime, '%H:%M')) <= hm(opening_times$till_time)[2])

datetimes$open <- ifelse(as.Date(datetimes$datetime) %within% 
                             interval(opening_times$from_date[1], 
                                      opening_times$till_date[1]), 
                         datetimes$datetime %within% 
                             interval(ymd_hm(paste(as.Date(datetimes$datetime), opening_times$from_time[1])),
                                      ymd_hm(paste(as.Date(datetimes$datetime), opening_times$till_time[1]))),
                         datetimes$datetime %within% 
                             interval(ymd_hm(paste(as.Date(datetimes$datetime), opening_times$from_time[2])),
                                      ymd_hm(paste(as.Date(datetimes$datetime), opening_times$till_time[2]))))

这篇关于合并日期和小时范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆