2017-10-04 85 views
1

我有一個包含日常數據的數據表。從這張數據表中,我想提取每週三獲得的每週數據點。如果星期三是假期,即在數據表中不可用,則應採取下一個可用數據點。 這裏,MWE:將日常數據轉換爲每週數據並處理假期問題

library(data.table) 
df <- data.table(date=as.Date(c("2012-06-25","2012-06-26","2012-06-27","2012-06-28","2012-06-29","2012-07-02","2012-07-03","2012-07-05","2012-07-06","2012-07-09","2012-07-10","2012-07-11","2012-07-12","2012-07-13","2012-07-16","2012-07-17","2012-07-18","2012-07-19","2012-07-20"))) 
df[,weekday:=strftime(date,'%u')] 

與輸出:

  date weekday 
1: 2012-06-25  1 
2: 2012-06-26  2 
3: 2012-06-27  3 
4: 2012-06-28  4 
5: 2012-06-29  5 
6: 2012-07-02  1 
7: 2012-07-03  2 
8: 2012-07-05  4 #here the 4th of July was skipped 
9: 2012-07-06  5 
10: 2012-07-09  1 
11: 2012-07-10  2 
12: 2012-07-11  3 
13: 2012-07-12  4 
14: 2012-07-13  5 
15: 2012-07-16  1 
16: 2012-07-17  2 
17: 2012-07-18  3 
18: 2012-07-19  4 
19: 2012-07-20  5 

我期望的結果,在這種情況下將是:

 date weekday 
2012-06-27  3 
2012-07-05  4 
2012-07-11  3 
2012-07-18  3 

有沒有獲得這比去的更有效的方法逐周通過for循環並檢查星期三數據點是否包含在數據中?我覺得必須有更好的方法,所以任何建議都將不勝感激!

工作溶液(以下伊莫的建議)

df[,weekday:=wday(date)] #faster way to get weekdays, careful: numbers increased by 1 vs strftime 
df[,numweek:=floor(as.numeric(date-date[1])/7+1)] #get continuous week numbers extending over end of years 
df[df[,.I[which.min(abs(weekday-4.25))],by=.(numweek)]$V1] #gets result 

回答

1

下面是使用在該查找最接近的值至3中的(使用.I)的位置的data.table聯接(即一個方法不是2,使用which.min(abs(as.integer(weekday)-3.25)))按周使用。

df[df[, .I[which.min(abs(as.integer(weekday)-3.25))], by=week(date)]$V1] 
     date weekday 
1: 2012-06-27  3 
2: 2012-07-05  4 
3: 2012-07-11  3 
4: 2012-07-18  3 

需要注意的是,如果你的真實數據跨越年,那麼你需要使用by=.(week(date), year(date))


還要注意的是有一個data.table功能wday即會直接返回一週中的一天整數。它比由strftime返回的字符整數值大1,因此如果您想直接使用它,則需要進行調整。

從單變量的data.table,你會做

df[, weekday := wday(date)] 
df[df[, .I[which.min(abs(weekday-4.25))], by=week(date)]$V1] 
     date weekday 
1: 2012-06-27  4 
2: 2012-07-05  5 
3: 2012-07-11  4 
4: 2012-07-18  4 

注意,日期符合上面。

+0

謝謝@Imo,這很好。剩下的唯一不幸的細節是該方法在年底前的行爲(我的數據確實跨越了幾年)。 例如:2010-12-29是週三,2011-01-05是週三,兩者都不是假期。但是,由於我們按周和年排序,2010年仍有一個開始的一週,因此該方法也會在2010-12-31的最後一天返回。 有沒有辦法來防止這種情況?刪除每年的所有最後日期可能是相當危險的,因爲有些人可能仍然需要。 – Daedalus

+0

可能的解決方法是在這個子集之後對日期進行區分(如'dat [,dtDiff:= diff(date)]')。如果該值小於5(或大約),則存在問題。對於這樣的行,也許選擇星期三(原始設置中的「週日== 3」)。 – lmo