R 将每日数据转换为每周数据并处理假期

R 将每日数据转换为每周数据并处理假期,r,data.table,R,Data.table,我有一个包含每日数据的数据表。从这个数据表中,我想提取每个星期三获得的每周数据点。如果星期三是假日,即数据表中不可用,则应取下一个可用数据点。 这里是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

我有一个包含每日数据的数据表。从这个数据表中,我想提取每个星期三获得的每周数据点。如果星期三是假日,即数据表中不可用,则应取下一个可用数据点。 这里是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
2012-06-27       3
2012-07-05       4
2012-07-11       3
2012-07-18       3
有没有比每周通过for循环检查星期三数据点是否包含在数据中更有效的方法?我觉得一定有更好的办法,所以任何建议都将不胜感激

工作解决方案(按照Imo的建议)

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

这里有一种方法使用data.table上的联接,使用查找最接近3的值的位置(使用
.I
)(这不是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=(周(日期)、年(日期))


还请注意,有一个
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

请注意,日期与上述日期一致。

谢谢@Imo,这非常有效。唯一令人遗憾的细节是该方法在年底前后的表现(我的数据确实跨越了几年)。示例:2010-12-29是星期三,2011-01-05是星期三,两者都不是假日。但由于我们按周和年排序,2010年还有一个开始周,因此该方法还返回一年的最后一天,2010-12-31。有没有办法防止这种情况?仅仅删除每年的所有最后日期可能是非常危险的,因为可能仍然需要一些日期。一种可能的解决方法是在该子集之后使用不同的日期(如
dat[,dtDiff:=diff(date)]
)。如果该值小于5(大约),则存在问题。对于这样的行,可以选择星期三(原始设置中的
weekday==3
)。
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