在R中生成每个月的最后一天的日期序列

3
如果我提供起始日期和结束日期,以及一个频率,我应该能够生成从开始到结束的日期序列,使得:
1)日期是每月的最后一天。
2)我可以将序列的频率设置为12的任何因子(相对于12个月)。例如,如果频率为3,则表示有4个月的间隔或间隙。
对于(1),下面的函数给出了一个输出,间隔为3个月(即季度),但它不给出当月的最后一天日期。
    DateSeq<-function(st,en, freq){
    seq(st, en, by = paste(as.character(12/freq), "months"))
    }
    DateSeq(as.Date("2015-01-01"),as.Date("2018-03-03"),4)

如何将这个转换为一个序列,使我得到最后一天?给我一个简单的代码。

3
也许 DateSeq(as.Date("2015-02-01"),as.Date("2018-04-03"),4)-1 的意思是生成从 2015 年 2 月 1 日到 2018 年 4 月 3 日之间,每隔 4 天的日期序列,并将结果减去 1。 - akrun
1
抱歉,我不知道您如何定义优雅。这只是从函数中减去1。 - akrun
2
好的,那么你应该在帖子中提到这一点。我以为你的日期会是每个月的第一天。 - akrun
lubridate::ceiling_date(DateSeq(as.Date("2015-01-10"),as.Date("2018-03-20"),4), 'month')-1 怎么样? - akrun
1
@akrun 把它写成一个答案。 - Dom Jo
显示剩余15条评论
3个回答

7
这将提供一个从st年/月到en年/月的月底日期序列。
library(zoo)
as.Date(seq(as.yearmon(st), as.yearmon(en), by = 1 / freq), frac = 1)

在上述代码中,sten可以是任何转换为yearmon的类,包括yearmon本身、Date、字符字符串或数字。例如:"2000-02-01""2000-02"as.Date("2000-02-01")2000+1/12
如果en是一个日期,并且序列的结束日期不应晚于en,则将as.yearmon(en)替换为以下内容,如果en不在月末,则减去1/12。
as.yearmon(en) - (as.Date(en) < as.Date(as.yearmon(en), frac = 1)) / 12

同样地,如果st是一个日期,并且序列的起始日期不晚于st,则使用相同的思路,在st不在月底时用1/12进行减法,并将as.yearmon(st)替换为即可。
as.yearmon(st) - (as.Date(st) < as.Date(as.yearmon(st), frac = 1)) / 12

关于我们是否真的需要日期,存在一些问题,因为它们总是在月底。似乎重点是创建年/月序列,月底日期只是表示这一点的一种方式。 一个更简单的方法是直接使用yearmon序列。

seq(as.yearmon(st), as.yearmon(en), by = 1 / freq)

2

在使用seq之前,我们可以使用来自zooas.yearmon将起始日期和结束日期更改为月份的开始,并通过相同的转换使用as.yearmon将其转换为该月份的最后一天。

library(zoo)
DateSeq <- function(st, en, freq) {
  st <- as.Date(as.yearmon(st)) 
  en <- as.Date(as.yearmon(en)) 
  as.Date(as.yearmon(seq(st, en, by = paste(as.character(12/freq), "months"))), frac = 1)

 }
DateSeq(as.Date("2015-01-31"),as.Date("2018-03-03"),4)
#[1] "2015-01-31" "2015-04-30" "2015-07-31" "2015-10-31" "2016-01-31" "2016-04-30" "2016-07-31" "2016-10-31" "2017-01-31"
#[10] "2017-04-30" "2017-07-31" "2017-10-31" "2018-01-31"

@G.Grothendieck 写成答案吧。看起来是更优雅的代码。 - Dom Jo

0

使用我的包timeplyr中的time_seq()方法,可以处理月度序列。

# remotes::install_github("NicChr/timeplyr")
library(timeplyr)

time_seq("2015-01-31", "2018-03-03", by = "3 months")
#>  [1] "2015-01-31" "2015-04-30" "2015-07-31" "2015-10-31" "2016-01-31"
#>  [6] "2016-04-30" "2016-07-31" "2016-10-31" "2017-01-31" "2017-04-30"
#> [11] "2017-07-31" "2017-10-31" "2018-01-31"

使用 reprex v2.0.2 于2023年4月11日创建

它也可以处理zoo的yearmon类。

library(lubridate)
time_range <- zoo::as.yearmon(ymd(c("2015-01-31", "2018-03-03")))

time_span(time_range, by = 3/12)
#>  [1] "Jan 2015" "Apr 2015" "Jul 2015" "Oct 2015" "Jan 2016" "Apr 2016"
#>  [7] "Jul 2016" "Oct 2016" "Jan 2017" "Apr 2017" "Jul 2017" "Oct 2017"
#> [13] "Jan 2018"

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