如何从R中的日期减去月份?

时间:2011-03-07 22:05:07

标签: r

我试图从日期中减去 n 个月,如下所示:

maturity <- as.Date("2012/12/31")

m <- as.POSIXlt(maturity)

m$mon <- m$mon - 6

但结果日期为01-Jul-2012,而不是30-Jun-2012,正如我所料。 有没有简短的方法来获得这样的结果?

提前致谢

4 个答案:

答案 0 :(得分:70)

1) seq.Date 。请注意,六月只有30天,所以它不能给6月31日,而是它给7月1日。

seq(as.Date("2012/12/31"), length = 2, by = "-6 months")[2]
## [1] "2012-07-01"

如果我们知道它是在月底,我们可以这样做:

seq(as.Date(cut(as.Date("2012/12/31"), "month")), length=2, by="-5 month")[2]-1
## "2012-06-30"

2) yearmon 。此外,如果我们知道它是月末,那么我们可以像这样使用动物园包的"yearmon"类:

ibrary(zoo)
as.Date(as.yearmon(as.Date("2012/12/31")) -.5, frac = 1)
## [1] "2012-06-30"

这会将日期转换为"yearmon"减去6个月(一年的.5),然后使用"Date"将其转换回frac=1,这意味着月末({{ 1}}意味着月初)。与以前的解决方案相比,它也具有自动向量化的优势,即frac=0可能是日期的向量。

请注意,如果as.Date(...)类仅用作表示月份的方式,那么我们可以完全摆脱它并直接使用"Date",因为它首先模拟了我们想要的东西:< / p>

"yearmon"

3) mondate 。第三种解决方案是mondate软件包,它的优势在于它在6个月前返回月末,而不必知道我们是月末:

as.yearmon("2012-12") - .5
## [1] "Jun 2012"

这也是矢量化的。

4) lubridate 。这个润滑的答案已根据包装中的变化而改变:

library(mondate)
mondate("2011/12/31") - 6
## mondate: timeunits="months"
## [1] 2011/06/30

lubridate也被矢量化。

5) sqldf / SQLite

library(lubridate)
as.Date("2012/12/31") %m-% months(6)
## [1] "2012-06-30"

或者如果我们知道我们在月末:

library(sqldf)
sqldf("select date('2012-12-31', '-6 months') as date")
##         date
## 1 2012-07-01

答案 1 :(得分:4)

你可以使用lubridate包来实现这个

library(lubridate)
maturity <- maturity %m-% months(6)

没有理由改变日期字段。

您可以通过

将日期字段设置回该月的最后一天
day(maturity) <- days_in_month(maturity)
祝你好运!!!

答案 2 :(得分:0)

从技术上讲,您不能在所有日期中添加/减去1个月(尽管您可以在所有日期中添加/减去30天,但是我想这不是您想要的)。我认为这就是您要寻找的

> lubridate::ceiling_date(as.Date("2020-01-31"), unit = "month")
[1] "2020-02-01"
> lubridate::floor_date(as.Date("2020-01-31"), unit = "month")
[1] "2020-01-01"

答案 3 :(得分:0)

lubridate在以下计算中可以正常使用:

library(lubridate)
as.Date("2000-01-01") - days(1)    # 1999-12-31
as.Date("2000-03-31") - months(1)  # 2000-02-29

但有时会失败:

as.Date("2000-02-29") - years(1)   # NA, should be 1999-02-28