I think this is what you need:
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 a specific date, which is the last day of the week.
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 calculate last_weekday_o_month as weekdays(last_weekdaydate_o_month) .
With a couple of 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
Frank source share