可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How do I find the last weekday (e.g., Wednesday) of the month using R? In the code below, I calculate the month, day of the month, week of the month, and weekday. There are 5 Wednesdays in January 2014, but only 4 Wednesdays in February 2014, so I cannot use max(week of the month) as a filter. Any help is appreciated although I prefer to use the base R functions.
DF <- data.frame(DATE = seq(as.Date("2014-01-01"), as.Date("2014-12-31"), "day")) DF$MONTH <- as.numeric(format(DF$DATE, "%m")) DF$DAY_OF_MONTH <- as.numeric(format(DF$DATE, "%d")) DF$WEEK_OF_MONTH <- ceiling(as.numeric(format(DF$DATE, "%d")) / 7) DF$WEEKDAY <- format(DF$DATE, "%A") DF
回答1:
I think this is what you're after:
DF$last_weekday_o_month <- ave( weekdays(DF$DATE), months(DF$DATE), FUN = function(x) tail(x[ !(x %in% c("Saturday","Sunday")) ], 1) )
To find the particular date that is the last weekday....
DF$last_weekdaydate_o_month <- ave( DF$DATE, months(DF$DATE), FUN = function(x) tail(x[ !(weekdays(x) %in% c("Saturday","Sunday")) ], 1) )
the result looks like...
DATE last_weekday_o_month last_weekdaydate_o_month 1 2014-01-01 Friday 2014-01-31 2 2014-01-02 Friday 2014-01-31 3 2014-01-03 Friday 2014-01-31 4 2014-01-04 Friday 2014-01-31 5 2014-01-05 Friday 2014-01-31 6 2014-01-06 Friday 2014-01-31 ... 360 2014-12-26 Wednesday 2014-12-31 361 2014-12-27 Wednesday 2014-12-31 362 2014-12-28 Wednesday 2014-12-31 363 2014-12-29 Wednesday 2014-12-31 364 2014-12-30 Wednesday 2014-12-31 365 2014-12-31 Wednesday 2014-12-31
If you did this first, of course you could compute last_weekday_o_month
as weekdays(last_weekdaydate_o_month)
.
With a couple packages, this can be done more elegantly/readably, as suggested by @RichardScriven:
library(data.table) setDT(DF)[, last_weekdaydate_o_month := last(DATE[!chron::is.weekend(DATE)]) , by = month(DATE)]
which gives
DATE last_weekdaydate_o_month 1: 2014-01-01 2014-01-31 2: 2014-01-02 2014-01-31 3: 2014-01-03 2014-01-31 4: 2014-01-04 2014-01-31 5: 2014-01-05 2014-01-31 --- 361: 2014-12-27 2014-12-31 362: 2014-12-28 2014-12-31 363: 2014-12-29 2014-12-31 364: 2014-12-30 2014-12-31 365: 2014-12-31 2014-12-31
回答2:
Here is a method using dplyr
. Essentially you group by the month, filter out the 'weekend' days and return the weekday of the last (i.e. max) day.
library(dplyr) DF <- data.frame(DATE = seq(as.Date("2014-01-01"), as.Date("2014-12-31"), "day")) DF %>% mutate(month = months(DATE), weekday = weekdays(DATE)) %>% group_by(month) %>% filter(!weekday %in% c("Saturday", "Sunday")) %>% summarise(last_weekday = weekdays(max(DATE))) Source: local data frame [12 x 2] month last_weekday 1 April Wednesday 2 August Friday 3 December Wednesday 4 February Friday 5 January Friday 6 July Thursday 7 June Monday 8 March Monday 9 May Friday 10 November Friday 11 October Friday 12 September Tuesday
回答3:
library(lubridate) x <- seq(as.Date("2007-12-31"), by="1 day", length.out=(Sys.Date() - as.Date("2007-12-31"))) library(plyr) df <- data.frame(date=x, year=year(x), month=month(x)) df[,"weekday"] <- weekdays(df[,"date"]) df<- df[! df[,"weekday"] %in% c("Saturday", "Sunday"),] df <- ddply(df, .(year, month), summarize, last=max(date))