2016-06-07 113 views
3

的序列下面的代碼有特定日期的名單,如果日期是最後一天,他一個月,在數據集(不是日曆上的)所有的日期,那麼它的標誌日期作爲本月的最後一天。確定第三個星期五的日期

data = data.frame(day = seq(as.Date("2014-01-01"),as.Date("2016-05-10"),"day"), weekday = weekdays (seq(as.Date("2014-01-01"),as.Date("2016-05-10"),"day"))) 
excludeDays <- c("Saturday", "Sunday") 
data <- subset(data, !weekdays(data$day) %in% excludeDays) #exclude weekend 
setDT(data) 
data[, LastDayInMonth := day == max(day), by = list(year(day),month(day) )] 
head(data,100) 

我還需要添加一列標誌(TRUE/FALSE)在本月的第三個星期五的數據中的任何星期五。任何想法呢?

例如2014年1月17日,2014年2月21日,2014年5月16日......等......是第3星期五。

謝謝。

+1

你可以直接用'data.table()'函數data.table。 – Arun

回答

2

以覆蓋邊界情況下,當數據開始本月中旬,你可以試試這個:

occ <- 3L # 3rd occurrence of selected weekday 
data[, ThirdFridayInMonth := weekday == "Friday" & 
     as.integer(day - lubridate::floor_date(day, "month")) %/% 7L + 1L == occ] 

這也適用於其他工作日當月,例如,以標誌每月第一個星期一。

編輯:根據要求解釋。

的基本思路是,在每個月的第一個星期五必須是第7天,每月的一個,第二個週五必須是8天至14等等之一。所以,lubridate::floor_date(day, "month")計算月day位於的第一天。現在,你建這是一個difftime對象需要被轉換成integer的差異。如果day碰巧是一個月的第一個,這是0。現在您使用整數除法%/%這對於第7天的月份,1的返回0的第二個7天等,然後通過添加1

編輯2調整:改進代碼

在編寫解釋時,我意識到代碼可以進一步改進。

我們可以直接使用一個月的第一天起它讓我們可以在計算日期和隨後轉換的差異整數

data[, ThirdFridayInMonth := weekday == "Friday" & 
     (mday(day) - 1) %/% 7L + 1L == occ] 

在這裏,我用mday代替as.integer(format(day, "%d"))data.table包的一部分)。

+0

你能解釋一下as.integer(day - lubridate :: floor_date ,「month」))%/%7L + 1L == occ]在幹什麼? – user3022875

+0

@ user3022875謝謝您的提問。我已經爲答案添加了解釋和改進的代碼。 – Uwe

2

試試這個 - 不data.table:

library(lubridate) 
library(dplyr) 
data <- data.frame(day = seq(as.Date("2014-01-01"), 
           as.Date("2016-05-10"),"day"), 
        weekday = weekdays(seq(as.Date("2014-01-01"), 
             as.Date("2016-05-10"),"day"))) 
data$year_month <- floor_date(data$day, unit = 'month') 
fri3 <- filter(data, weekday == 'Friday') %>% 
    group_by(year_month) %>% slice(3) 

data$Third_Fri <- data$day %in% fri3$day 

您可以刪除YEAR_MONTH後

2

另一種方式來做到這一點:

data[, is3Friday:=cumsum(weekday=="Friday"), by=substring(day, 1, 7)] 
data[, is3Friday:=ifelse(weekday=="Friday" & is3Friday==3, TRUE, FALSE)] 

data[is3Friday==TRUE] 
      day weekday LastDayInMonth is3Friday 
1: 2014-01-17 Friday   FALSE  TRUE 
2: 2014-02-21 Friday   FALSE  TRUE 
3: 2014-03-21 Friday   FALSE  TRUE 
4: 2014-04-18 Friday   FALSE  TRUE 
5: 2014-05-16 Friday   FALSE  TRUE 
6: 2014-06-20 Friday   FALSE  TRUE 
4
data[, numWeek := 1:.N, by = .(year(day), month(day), weekday)] 

data[numWeek == 3 & weekday == "Friday"] 

,或者添加爲列:

data[, is3rdFriday := numWeek == 3 & weekday == "Friday"] 

如果你在日曆中尋找第三個星期五,在您的數據相對於第三個星期五,那麼你就可以做到這一點更簡單:

data[, is3rdFriday := (mday(day) - 1) %/% 7 + 1 == 3 & weekday == "Friday"] 
+0

這有效,但數據在第二週開始時會出現一個特例。那麼第三個星期五算作第二個並且不會被標記爲 – user3022875

+0

要覆蓋角落案例,您可以執行'data [,ThirdFridayInMonth:= weekday ==「Friday」& as.integer(day - lubridate :: floor_date( (日期 - 月份「))%/%7L + 1L == 3L]' – Uwe

+0

@ user3022875從OP中不清楚你想要什麼 - 添加 – eddi

相關問題