【问题标题】:Find first Tuesday of Month查找每月的第一个星期二
【发布时间】:2012-11-19 06:15:57
【问题描述】:

我正在尝试编写一个函数,该函数将日期向量作为输入并返回日期向量——其中输出是与输入日期匹配的每月第一个星期二的日期。

所以2012-11-19 --> 2012-11-06

我在单个日期上取得了一些成功,但无法推广到矢量情况。有人可以帮忙吗?

这是我目前所拥有的:

firstTuesday <- function(tt){
  ct <- as.POSIXct(tt)
  lt <- as.POSIXlt(tt)
  firstOf <- as.POSIXlt(ct - 60*60*24* (lt$mday - 1))
  if (firstOf$wday > 2) 
  {
    adjDays <- (9 - firstOf$wday)
    firstTues <- as.POSIXlt(as.POSIXct(firstOf) + 60*60*24*adjDays)
  }
  else {
    adjDays  <- (2 - firstOf$wday)
    firstTues <- as.POSIXlt(as.POSIXct(firstOf) + 60*60*24*adjDays)
  }
  return(firstTues)
}

这适用于单个日期:firstTuesday(Sys.Date()) 但会为日期向量产生垃圾(我认为,由于if 不是向量化控制运算符的问题)。


我通过使用索引来解决我有限的理解。以下代码似乎可以解决问题。

firstTuesday <- function(tt){
  ct <- as.POSIXct(tt)
  lt <- as.POSIXlt(tt)
  firstOf <- as.POSIXlt(ct - 60*60*24* (lt$mday - 1))
  firstTue <- as.POSIXct(firstOf)
  idx <- firstOf$wday > 2
  firstTue[idx]  <- as.POSIXct(firstOf[idx]) + 60*60*24*(9 - firstOf$wday[idx])
  firstTue[!idx]  <- as.POSIXct(firstOf[!idx]) + 60*60*24*(2 - firstOf$wday[!idx])
  return(firstTue)
}

【问题讨论】:

  • 如果您使用时间和日期,我强烈推荐使用 lubridate 包。
  • 谢谢——也许我会的。我不愿意添加新的包依赖项,但也许这是值得的。

标签: r date


【解决方案1】:

这使用了 lubridate 并使逻辑更简单一些。给定一个日期向量,第二个函数将返回一个字符向量,类似于您的输入。您可以根据自己的需要进行更改。

library(lubridate)

getTuesday = function(x) {
    date = ymd(x)
    first = floor_date(date,"month")
    dow = sapply(seq(0,6),function(x) wday(first+days(x)))
    firstTuesday = first + days(which(dow==3)-1)
    return(firstTuesday)
}

getMultipleTuesdays = function(y) {
    tmp = lapply(y, getTuesday)
    tmp = lapply(tmp, as.character)
    return(unlist(tmp))
}

编辑

示例输入/输出

getMultipleTuesdays(c("2012-11-19","2012-11-19","2011-01-15"))
[1] "2012-11-06" "2012-11-06" "2011-01-04"

【讨论】:

  • 另外,将 3 其中(dow==3) 更改为 1-7 将允许您选择一周中的任何一天,星期日是第 1 天。
  • +1 / 接受。谢谢。您的示例确实解决了问题,并且是我自己(基本)解决方案的灵感。
【解决方案2】:

这是一个使用基函数的简单解决方案:

firstDayOfMonth <- function(dates, day="Mon", abbreviate=TRUE) {
  # first 7 days of month
  s <- lapply(as.Date(format(dates,"%Y-%m-01")), seq, by="day", length.out=7)
  # first day of month
  d <- lapply(s, function(d) d[weekdays(d,abbreviate)==day])
  # unlist converts to atomic, so use do.call(c,...) instead
  do.call(c, d)
}

好吧,也许最后的do.call 不是那么简单......但它是一个方便的知识。 :)

R> d <- as.Date(c("2012-11-19","2012-11-19","2011-01-15"))
R> firstDayOfMonth(d, "Tuesday", FALSE)
[1] "2012-11-06" "2012-11-06" "2011-01-04"

【讨论】:

  • 每当我看到使用字符串解析解决的日期答案时,我都会在嘴里吐一点;)(但我还是给了你一个赞成票)
  • @hadley: 哇,太棒了。 :P 它比使用 POSIXlt 更短更干净。
  • +1 / 谢谢约书亚。这确实很有帮助。我不会切换接受,因为 40.7k 比 59 大得多。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多