从今天的日期减去1个月会得到NA(缺失值)。

16

我有一个脚本,根据一些时间段对我的数据进行子集处理,并希望将发生在最近一个月内的所有记录都进行子集处理。

但是,如果我尝试从今天的日期减去一个月,它会得到一个NA:

> today <- Sys.Date()
> today
[1] "2017-03-29"
> today - months(1)
[1] NA

我已经加载了lubridate但是我认为这个计算是使用基础的R执行的。如果我减去2个或更多月,它可以正常工作:

> today - months(2)
[1] "2017-01-29"
> today - months(3)
[1] "2016-12-29"

有人对发生的事情有任何想法吗?

更新:我认为这与简单的日期减法未处理闰年情况有关(2017年不是闰年,因此"2017-02-29"不存在)。

是否有其他考虑闰年的包/函数? 对于上述示例,我希望答案恢复到上个月的最后一天,即:

today - months(1)
# Should yield:
"2017-02-28"

这个计算是否应该在今天和昨天给出相同的结果(或者按照ISO惯例应该如何处理)?

> sessionInfo()
R version 3.3.2 (2016-10-31)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

locale:
[1] LC_COLLATE=English_United Kingdom.1252  LC_CTYPE=English_United Kingdom.1252   
[3] LC_MONETARY=English_United Kingdom.1252 LC_NUMERIC=C                           
[5] LC_TIME=English_United Kingdom.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets  methods   base     

other attached packages:
 [1] xlsx_0.5.7         xlsxjars_0.6.1     rJava_0.9-8        MRAtools_0.6.8     stringdist_0.9.4.4 stringr_1.2.0     
 [7] stringi_1.1.3      lubridate_1.6.0    data.table_1.10.4  PKI_0.1-3          base64enc_0.1-3    digest_0.6.12     
[13] getPass_0.1-1      RPostgreSQL_0.5-1  DBI_0.5-1         

loaded via a namespace (and not attached):
[1] magrittr_1.5   rstudioapi_0.6 tools_3.3.2    parallel_3.3.2
2个回答

28

计算月份的确是通过基础R执行的,但不是你想象的那种方式。Months函数用于获取日期对象的月份。

#Example
today <- Sys.Date()
months(today)
[1] "March"

为了添加或减去月份,您应该使用%m+%lubridate

today <- Sys.Date()
today %m+% months(-1)
[1] "2017-02-28"

在使用 lubridate 时,months 函数被覆盖,不像基本的 R 那样运行。 - TARehman
@TARehman 不是,lubridate函数是month而不是months。基础R有months函数。 - Pierre Lapointe
Base R的months函数不能接受数字,但是当我加载lubridate时,我可以给months一个数字。为什么会这样呢?请参阅文档:https://www.rdocumentation.org/packages/lubridate/versions/1.6.0/topics/quick_periods,它似乎表明它正在覆盖基本的R函数。 - TARehman
我认为是%m+%函数接受更多的输入,因为lubridate::months(Sys.Date())会报错,提示months不是lubridate的一部分。 - Pierre Lapointe
这真的很奇怪,因为当加载lubridate时,months(1)返回"1m 0d 0H 0M 0S"。我不是lubridate的重度用户,所以这只是为了我的信息而已。 :) - TARehman
@TARehman 我同意。不确定为什么在加载lubridate之后,months(1)会起作用。 - Pierre Lapointe

5
一个月前在这个上下文中没有明确定义。2月29日只存在于闰年。
请参阅 lubridate 文档
注意: 当涉及到不存在的日期时(如非闰年的2月29日),使用期间进行算术运算可能会导致未定义的行为。请参见 Period-class 以获取更多详细信息,以及 %m+% 和 add_with_rollback 以获取替代操作。 lubridate 包可以处理您正在进行的操作,但是您需要使用 %m+% 进行操作。

2
已接受 @P Lapointe 的答案,但因为他指向了 lubridate 上关于这个主题的具体帮助,所以给予 +1。 - Amy M
更新链接 - https://lubridate.tidyverse.org/reference/mplus.html - M.Viking

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接