【问题标题】:Create end of the month date from a date variable从日期变量创建月末日期
【发布时间】:2012-03-19 05:17:57
【问题描述】:

我有一个包含日期变量的大型数据框,它反映了当月的第一天。有没有一种简单的方法可以创建一个新的数据框日期变量来表示该月的最后一天?

以下是一些示例数据:

date.start.month=seq(as.Date("2012-01-01"),length=4,by="months")
df=data.frame(date.start.month)
df$date.start.month

"2012-01-01" "2012-02-01" "2012-03-01" "2012-04-01"

我想返回一个新变量:

"2012-01-31" "2012-02-29" "2012-03-31" "2012-04-30"

我尝试了以下方法,但没有成功:

df$date.end.month=seq(df$date.start.month,length=1,by="+1 months")

【问题讨论】:

  • 您的示例输出不符合问题。
  • 你也可以考虑使用 "yearmon" 类,它代表年/月,而不需要一开始就需要一天:library(zoo); ym <- as.yearmon("2012-01") + 0:3/12。如果您确实想要该月最后一天的日期,那么as.Date(ym, frac = 1)
  • G.Grothendieck:谢谢你的建议,以后我一定要记住使用 yearmon 类来处理这类日期数据。

标签: r date dataframe


【解决方案1】:

要获得月末,您只需创建一个 Date 向量,其中包含所有后续月份的第一个并减去 1 天。

date.end.month <- seq(as.Date("2012-02-01"),length=4,by="months")-1
date.end.month
[1] "2012-01-31" "2012-02-29" "2012-03-31" "2012-04-30"

【讨论】:

  • 谢谢詹姆斯,但这似乎在数据框架结构中不起作用。
  • 图书馆(lubridate) date.start.month=seq(as.Date("2012-01-01"),length=4,by="months") df=data.frame(date .start.month) df$date.end.month=df$date.start.month+months(1)-days(1) df$date.start.month df$date.end.month "2012-01-01 " "2012-02-01" "2012-03-01" "2012-04-01" "2012-01-31" "2012-02-29" "2012-03-31" "2012-04-30"
  • @MikeTP 它看起来对我有用,但您的示例输出令人困惑:为什么是 4 月 27 日?
  • James:抱歉……4 月 27 日是一个错字,应该是“2012-04-30”。感谢您的帮助。
【解决方案2】:

这是使用lubridate 包的另一种解决方案:

date.start.month=seq(as.Date("2012-01-01"),length=4,by="months")
df=data.frame(date.start.month)

library(lubridate)
df$date.end.month <- ceiling_date(df$date.start.month, "month") - days(1)
df$date.end.month
[1] "2012-01-31" "2012-02-29" "2012-03-31" "2012-04-30"

这使用了上面 James 给出的相同概念,即获取下个月的第一天并减去一天。

顺便说一句,即使输入日期不一定是当月的第一天,这也可以工作。例如,今天是每月 27 日,它仍然返回正确的当月最后一天:

ceiling_date(Sys.Date(), "month") - days(1)
[1] "2017-07-31"

【讨论】:

  • days(1) 实际上是不必要的。做ceiling_date(Sys.Date(), "month") - 1 就足够了。只为未来的访客...
【解决方案3】:

使用timeDate 包中的 timeLastDayInMonth:

df$eom<-timeLastDayInMonth(df$somedate)

【讨论】:

    【解决方案4】:
    library(lubridate)
     as.Date("2019-09-01") - days(1)
    [1] "2019-08-31"
    

    library(lubridate)
     as.Date("2019-09-01") + months(1) - days(1)
    [1] "2019-09-30"
    

    【讨论】:

      【解决方案5】:

      一个简单的解决方案是使用 yearmon 函数和 xts 包中的参数 frac=1frac 是一个介于 0 和 1 之间的数字,表示通过结果所代表的周期的分数。

      as.Date(as.yearmon(seq.Date(as.Date('2017-02-01'),by='month',length.out = 6)),frac=1)
      
      [1] "2017-02-28" "2017-03-31" "2017-04-30" "2017-05-31" "2017-06-30" "2017-07-31"
      

      或者,如果您更喜欢使用magrittr“管道”:

      seq.Date(as.Date('2017-02-01'),by='month',length.out = 6) %>%
               as.yearmon() %>% as.Date(,frac=1)
      
      [1] "2017-02-28" "2017-03-31" "2017-04-30" "2017-05-31" "2017-06-30" "2017-07-31"
      

      【讨论】:

        【解决方案6】:

        下面的函数可以完成这项工作(假设 dt 是标量)-

        month_end <- function(dt) {
            d <- seq(dt, dt+31, by="days")
            max(d[format(d,"%m")==format(dt,"%m")])
        }
        

        如果您有日期向量,请执行以下操作 -

        sapply(dates, month_end)
        

        【讨论】:

        • 这个功能不行。以“2019-01-31”为例,一切都崩溃了。
        【解决方案7】:

        你可以使用timeperiodsR

        date.start.month=seq(as.Date("2012-01-01"),length=4,by="months")
        df=data.frame(date.start.month)
        df$date.start.month
        
        # install.packages("timeperiodsR") 
        
        pm <- previous_month(df$date.start.month[1]) # get previous month
        
        start(pm) # first day of previous month
        end(pm)   # last day of previous month
        seq(pm)   # vector with all days of previous month
        

        【讨论】:

          【解决方案8】:

          我们也可以使用bsts::LastDayInMonth:

          transform(df, date.end.month = bsts::LastDayInMonth(df$date.start.month))
          
          #   date.start.month date.end.month
          # 1       2012-01-01     2012-01-31
          # 2       2012-02-01     2012-02-29
          # 3       2012-03-01     2012-03-31
          # 4       2012-04-01     2012-04-30
          

          【讨论】:

            猜你喜欢
            • 2015-10-10
            • 1970-01-01
            • 1970-01-01
            • 2021-12-06
            • 2014-10-04
            • 2013-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多