9

我想要一个计算每月特定天数的函数..

IE。13 年 11 月 -> 5 个星期五.. 而 13 年 12 月将返回 4 个星期五..

是否有一个优雅的函数可以返回这个?

library(lubridate)

num_days <- function(date){
x <- as.Date(date)  
start = floor_date(x, "month")
count = days_in_month(x)

d = wday(start) 
sol = ifelse(d > 4, 5, 4) #estimate that is the first day of the month is after Thu or Fri then the week will have 5 Fridays
sol
}

num_days("2013-08-01")
num_days(today())

有什么更好的方法来做到这一点?

4

3 回答 3

11

1)d是输入,一个Date类对象,例如d <- Sys.Date()。结果给出了包含 的年/月中的星期五数d。将 5 替换为 1 以获得星期一的数量:

first <- as.Date(cut(d, "month"))
last <- as.Date(cut(first + 31, "month")) - 1
sum(format(seq(first, last, "day"), "%w") == 5)

2)将最后一行替换为下一行。这里,第一项是从 Epoch 到下一个星期五在下个月的第一个或之后的星期五数,第二项是从 Epoch 到下一个星期五的第一个或之后的星期五d数月。同样,我们将所有 5 替换为 1 以获得星期一的计数。

ceiling(as.numeric(last + 1 - 5 + 4) / 7) - ceiling(as.numeric(first - 5 + 4) / 7)

第二种解决方案稍长(尽管它的行数相同),但它具有矢量化的优点,即d可以是日期矢量。

更新:添加了第二个解决方案。

于 2013-11-11T18:59:24.177 回答
2

有很多方法可以做到这一点。这是一个:

countFridays <- function(y, m) { 
    fr <- as.Date(paste(y, m, "01", sep="-")) 
    to <- fr + 31       
    dt <- seq(fr, to, by="1 day")      
    df <- data.frame(date=dt, mon=as.POSIXlt(dt)$mon, wday=as.POSIXlt(dt)$wday)  
    df <- subset(df, df$wday==5 & df$mon==df[1,"mon"])         
    return(nrow(df))     
}

它创建了月份的第一天,以及接下来的几个月中的一天。

然后它创建月份索引(在 0 到 11 范围内,但我们仅将其用于比较)和工作日的数据框。

然后我们将子集划分为 a) 在同一个月和 b) 在星期五。那是您的结果集,我们返回行数作为您的答案。

请注意,这仅使用基本 R 代码。

于 2013-11-11T18:44:07.133 回答
2

不使用lubridate-

#arguments to pass to function:
whichweekday <- 5
whichmonth <- 11
whichyear <- 2013

#function code:    
firstday <- as.Date(paste('01',whichmonth,whichyear,sep="-"),'%d-%m-%Y')
lastday <- if(whichmonth == 12) { '31-12-2013' } else {seq(as.Date(firstday,'%d-%m-%Y'), length=2, by="1 month")[2]-1}
sum(
  strftime(
seq.Date(
  from = firstday,
  to = lastday,
  by = "day"),
'%w'
) == whichweekday)
于 2013-11-11T18:48:17.597 回答