【问题标题】:Is there an easy way to tell if an interval overlaps a weekend in R?有没有一种简单的方法可以判断间隔是否与 R 中的周末重叠?
【发布时间】:2016-05-10 23:12:35
【问题描述】:

我有一系列的到达和离开日期。我想知道这些日期是否与周末重叠。我可以编写一个自定义函数来遍历间隔中的每一天,看看它们是否是周末。有没有更简单的方法可以更好地扩展?

我正在使用 lubridate,但如果这样可以让我的工作更轻松,我很乐意使用不同的日期包。

【问题讨论】:

  • 我尝试的伪代码是:if (end - beginning > 5) TRUE else if (beginning <= Sunday & end >= Saturday) TRUE。主要优点是您不必声明结束和开始之间的所有日期。
  • 您可以使用weekdays 在基数 R 中为工作日分配数字,星期一 = 1,星期二 = 2 等等。从那里确定离开的工作日是否

标签: r date lubridate


【解决方案1】:

这个 base-R 解决方案怎么样:

# make a set of sequences from beginning and ending dates and test with:
as.POSIXlt(x)$wday %in% c(0,6)

这将提供一个 TRUE/FALSE 向量,您可以通过以下方式确定序列中的任何项目是否为 TRUE:

max( as.POSIXlt(x)$wday %in% c(0,6) )

【讨论】:

  • 如何在给定间隔(或只是开始/结束日期)的情况下轻松制作日期序列?难道我不必每天循环进行吗?
【解决方案2】:

使用 a_date 作为到达日期和 d_date ansd 出发日期,这样的事情可以工作:

require(lubridate)
weekend_overlap <-    ifelse(wday(a_date) %in% c(1, 7) || 
   wday(d_date) %in% c(1, 7) || 
   interval(a_date,d_date)/ddays(1) > 4,TRUE,FALSE)

【讨论】:

  • 我喜欢这个主意,但是当间隔跨越星期五:星期一时它会失败。那是 4 天,包括周末。
  • 我知道我错过了一些东西。好的,我们可以用 wday(a_date) &gt; wday(d_date) 替换 `interval(a_date,d_date)/ddays(1) > 4` 吗?第二个条件检查 week 是否改变
  • 受您的想法启发,我得出了这个结论: containsWeekend 6,TRUE,FALSE) }
【解决方案3】:

这里有一个更通用(矢量化)的函数,用于检查区间from-to 是否包含某个工作日(1-7):

#' Check if a weekday is within an interval
#' 
#' @param wday Day of week (integer 1-7)
#' @param from Date. Can be a vector.
#' @param to Date. Same length as `from` and must be greater than `from`.
#' @param week_start 1 = Monday. 7 = Sunday
#' 
wday_in_interval = function(wday, from, to, week_start = 1) {
  if (wday < 1 | weekday > 7) 
    stop("wday must be an integer from 1 to 7.")
  if (week_start)
    wday = 1 + (((wday - 2) + week_start ) %% 7)  # Translate wday to week_start = 1 (ISO standard)
  if (any(from > to, na.rm = TRUE))
    stop("`from` must come before `to`")
  
  # If the interval is greater than a week, it trivially contains any weekday
  over_a_week = difftime(from, to, units = "days") >= 7
  
  # Check if weekday is both smaller/greater than "from" and "to"
  days_from = as.numeric(strftime(from, "%u"))
  days_to = as.numeric(strftime(to, "%u"))
  contains_weekday = ifelse(
    strftime(from, "%V") == strftime(to, "%V"),  # Dates are in the same week?
    yes = wday >= days_from & wday <= days_to,
    no = wday >= days_from | wday <= days_to  # 
  )
  
  return(over_a_week | contains_weekday)
}

找出一个时间间隔是否包括周末只需检查该时间间隔是否不包括周六或周日:

library(dplyr)
tibble::tibble(
  timestamp = seq(as.POSIXct("2020-09-03 0:00"), as.POSIXct("2020-09-8 12: 00"), length.out = 10),
  overlaps_saturday = wday_in_interval(6, from = lag(timestamp), to = timestamp),
  overlaps_sunday = wday_in_interval(7, from = lag(timestamp), to = timestamp),
  overlaps_weekend = overlaps_saturday | overlaps_sunday
)

结果:

# A tibble: 10 x 4
   timestamp           overlaps_saturday overlaps_sunday overlaps_weekend
   <dttm>              <lgl>             <lgl>           <lgl>           
 1 2020-09-03 00:00:00 NA                NA              NA              
 2 2020-09-03 14:40:00 FALSE             FALSE           FALSE           
 3 2020-09-04 05:20:00 FALSE             FALSE           FALSE           
 4 2020-09-04 20:00:00 FALSE             FALSE           FALSE           
 5 2020-09-05 10:40:00 TRUE              FALSE           TRUE            
 6 2020-09-06 01:20:00 TRUE              TRUE            TRUE            
 7 2020-09-06 16:00:00 FALSE             TRUE            TRUE            
 8 2020-09-07 06:40:00 FALSE             TRUE            TRUE            
 9 2020-09-07 21:20:00 FALSE             FALSE           FALSE           
10 2020-09-08 12:00:00 FALSE             FALSE           FALSE  

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    • 2012-04-30
    相关资源
    最近更新 更多