R语言日期格式%Y-%V异常:2017-01-01返回2017-52不符合预期
R语言日期格式化:周数与年份不匹配的问题解析
问题重现
我没法理解R语言的以下运行行为:
> format(as.Date("2017-01-01"), "%Y-%V") [1] "2017-52" > as.Date("2017-01-01") [1] "2017-01-01" > format(as.Date("2017-01-01")-1, "%Y-%V") [1] "2016-52"
按照ISO 8601的周规则,2017年1月1日所在的周在2017年仅包含不足4天,我预期第一行输出应该是2016-52而非2017-52,请问问题出在哪里?
运行环境信息
sessionInfo() # R version 3.4.1 (2017-06-30) # Platform: x86_64-w64-mingw32/x64 (64-bit) # 运行环境:Windows Server >= 2012 x64 (build 9200) # Matrix products: default # 区域设置: # [1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 # [3] LC_MONETARY=English_United States.1252 LC_NUMERIC=C # [5] LC_TIME=English_United States.1252 # 已附加的基础包: # [1] parallel splines stats graphics grDevices utils datasets methods base # 其他已附加包: # [1] plotly_4.7.1 highcharter_0.5.0 flexdashboard_0.5 xts_0.10-0 zoo_1.8-0 # [6] rmdformats_0.3.3 dygraphs_1.1.1.4 pROC_1.10.0 elasticnet_1.1 lars_1.2 # [11] here_0.1 brew_1.0-6 Hmisc_4.0-3 Formula_1.2-2 stringr_1.2.0 # [16] devtools_1.13.3 RODBC_1.3-15 caret_6.0-77 testthat_1.0.2 rmarkdown_1.6 # [21] gbm_2.1.3 lattice_0.20-35 survival_2.41-3 data.table_1.10.4 rgdal_1.2-11 # [26] sp_1.2-5 colorRamps_2.3 gridExtra_2.3 DT_0.2 knitr_1.17 # [31] reshape2_1.4.2 scales_0.5.0.9000 ggmap_2.6.1 dplyr_0.7.3 purrr_0.2.3 # [36] readr_1.1.1 tidyr_0.7.1 tibble_1.3.4 ggplot2_2.2.1.9000 tidyverse_1.1.1 # [41] pacman_0.4.6 # 通过命名空间加载(未附加): # [1] readxl_1.0.0 backports_1.1.0 plyr_1.8.4 igraph_1.1.2 lazyeval_0.2.1 digest_0.6.12 foreach_1.4.3 htmltools_0.3.6 # [9] magrittr_1.5 checkmate_1.8.3 memoise_1.1.0 cluster_2.0.6 recipes_0.1.0 modelr_0.1.1 gower_0.1.2 dimRed_0.1.0 # [17] jpeg_0.1-8 colorspace_1.3-2 rvest_0.3.2 haven_1.1.0 crayon_1.3.4 jsonlite_1.5 bindr_0.1 iterators_1.0.8 # [25] glue_1.1.1 DRR_0.0.2 gtable_0.2.0 ipred_0.9-6 questionr_0.6.1 kernlab_0.9-25 ddalpha_1.2.1 quantmod_0.4-11 # [33] DEoptimR_1.0-8 maps_3.2.0 miniUI_0.1.1 Rcpp_0.12.14 viridisLite_0.2.0 xtable_1.8-2 htmlTable_1.9 foreign_0.8-69 # [41] mapproj_1.2-5 stats4_3.4.1 lava_1.5 prodlim_1.6.1 htmlwidgets_0.9 httr_1.3.1 RColorBrewer_1.1-2 geosphere_1.5-5 # [49] acepack_1.4.1 pkgconfig_2.0.1 nnet_7.3-12 rlang_0.1.2 munsell_0.4.3 cellranger_1.1.0 tools_3.4.1 broom_0.4.2 # [57] evaluate_0.10.1 yaml_2.1.14 ModelMetrics_1.1.0 robustbase_0.92-7 RgoogleMaps_1.4.1 bindrcpp_0.2 nlme_3.1-131 mime_0.5 # [65] RcppRoll_0.2.2 xml2_1.1.1 compiler_3.4.1 rstudioapi_0.7 curl_2.8.1 png_0.1-7 stringi_1.1.5 highr_0.6 # [73] forcats_0.2.0 Matrix_1.2-10 psych_1.7.8 httpuv_1.3.5 R6_2.2.2 latticeExtra_0.6-28 bookdown_0.5 codetools_0.2-15 # [81] MASS_7.3-47 assertthat_0.2.0 CVST_0.2-1 proto_1.0.0 rprojroot_1.2 rjson_0.2.15 withr_2.1.0.9000 mnormt_1.5-5 # [89] rlist_0.4.6.1 hms_0.3 grid_3.4.1 rpart_4.1-11 timeDate_3012.100 class_7.3-14 TTR_0.23-2 shiny_1.0.5 # [97] lubridate_1.6.0 base64enc_0.1-3
问题原因与解决方法
这其实是日期格式符搭配错误导致的:
%V是按照ISO 8601标准定义的周数,它对应的年份应该用%G(ISO周的年份),而不是%Y(日期的日历年份)。- 2017年1月1日是周日,按照ISO 8601规则,它属于2016年的第52周,但你用了
%Y,它只会提取日期本身的日历年份2017,所以就出现了2017-52这个看似矛盾的结果。
如果要得到符合ISO周规则的正确年份+周数组合,应该把%Y换成%G:
format(as.Date("2017-01-01"), "%G-%V") # [1] "2016-52"
另外补充一下格式符的对应关系:
- 如果你用的是
%U(周日为一周第一天的周数)或%W(周一为一周第一天的周数),搭配%Y是合理的; - 但
%V是ISO标准周数,必须搭配%G才能得到正确的周年份,否则就会出现日历年份和ISO周数不匹配的情况。
内容的提问来源于stack exchange,提问作者YCR
相关产品推荐
相关产品推荐

