我正在致力于将基于周的日期转换为基于月份的日期.
在检查我的工作时,我在我的数据中发现了以下问题,这是对简单调用的结果 as.Date()
as.Date("2016-50-4", format = "%Y-%U-%u")
as.Date("2016-50-5", format = "%Y-%U-%u")
as.Date("2016-50-6", format = "%Y-%U-%u")
as.Date("2016-50-7", format = "%Y-%U-%u") # this is the problem
Run Code Online (Sandbox Code Playgroud)
前面的代码生成前3行的正确日期:
"2016-12-15"
"2016-12-16"
"2016-12-17"
Run Code Online (Sandbox Code Playgroud)
然而,最后一行代码可以追溯到1周:
"2016-12-11"
Run Code Online (Sandbox Code Playgroud)
谁能解释一下这里发生了什么?
一年中的一周工作可能变得非常棘手.您可以尝试使用ISOweek包转换日期:
# create date strings in the format given by the OP
wd <- c("2016-50-4","2016-50-5","2016-50-6","2016-50-7", "2016-51-1", "2016-52-7")
# convert to "normal" dates
ISOweek::ISOweek2date(stringr::str_replace(wd, "-", "-W"))
Run Code Online (Sandbox Code Playgroud)
结果
#[1] "2016-12-15" "2016-12-16" "2016-12-17" "2016-12-18" "2016-12-19" "2017-01-01"
Run Code Online (Sandbox Code Playgroud)
是一流的Date.
请注意,基于ISO周的日期格式在周数之前yyyy-Www-d有一个大写W.这需要将其与标准的基于月份的日期格式区分开来yyyy-mm-dd.
因此,为了转换OP提供的日期字符串,ISOweek2date()必须W在第一个连字符之后插入一个连字符,这是-通过-W在每个字符串中替换第一个连字符来完成的.
另请注意,ISO周从星期一开始,一周的日期编号为1到7.属于ISO周的年份可能与日历年不同.这可以从上面的基于周的日期2016-W52-7转换为的样本日期中看出2017-01-01.
ISOweek包裹早在2011年,%G,%g,%u,和%V格式规范并不适用于strptime()在R的Windows版本这是恼人的,因为我已经准备每周的报告,包括周环周的比较.我花了几个小时找到一个解决方案来处理ISO周,ISO工作日和ISO年.最后,我最终创建了ISOweek包并在CRAN上发布它.今天,该软件包仍然有其优点,因为上述格式在输入时被忽略(?strptime详情请参见参考资料).
正如@lmo在评论中所说的那样,%u工作日代表十进制数字(1-7,周一为1),并%U代表星期几作为十进制数字(00-53),使用星期日作为第一天.因此,as.Date("2016-50-7", format = "%Y-%U-%u")将导致"2016-12-11".
但是,如果应该给出"2016-12-18",那么你应该使用星期一作为开始日的周格式.根据文档,?strptime您可以预期格式"%Y-%V-%u"会给出正确的输出,其中%V一年中的星期为十进制数(01-53),星期一为第一天.
不幸的是,它没有:
> as.Date("2016-50-7", format = "%Y-%V-%u")
[1] "2016-01-18"
Run Code Online (Sandbox Code Playgroud)
然而,在解释结束时,%Vsais "接受但忽略了输入"意味着它将无效.
您可以按如下方式规避此行为以获取正确的日期:
# create a vector of dates
d <- c("2016-50-4","2016-50-5","2016-50-6","2016-50-7", "2016-51-1")
# convert to the correct dates
as.Date(paste0(substr(d,1,8), as.integer(substring(d,9))-1), "%Y-%U-%w") + 1
Run Code Online (Sandbox Code Playgroud)
这使:
[1] "2016-12-15" "2016-12-16" "2016-12-17" "2016-12-18" "2016-12-19"
Run Code Online (Sandbox Code Playgroud)