【问题标题】:How to use cut function on dates如何在日期上使用剪切功能
【发布时间】:2022-01-03 17:35:03
【问题描述】:

我有以下两个日期:

dates <- c("2019-02-01",   "2019-06-30")

我想从以上两个日期创建以下垃圾箱:

2019-05-30, 2019-04-30, 2019-03-31, 2019-02-28 

我使用了cut函数和seq,

dt <- as.Date(dates)

cut(seq(dt[1], dt[2], by = "month"), "month")

但这不会产生正确的结果。

您能否介绍一下在日期上使用 cut 功能?

【问题讨论】:

  • ?cut.Date 会有所帮助。
  • lubridate 有一个功能回滚,它将日期转换为上个月的最后一个日期。 rollback(seq(dt[1], dt[2], by = "month"))[-1] 这将产生以下输出 [1] "2019-02-28" "2019-03-31" "2019-04-30" "2019-05-31" 您也可以使用 sort 函数按降序获取输出

标签: r date binning


【解决方案1】:

我们假设需要的是介于但不包括 dates 中的两个日期之间的所有月末。在问题中 dates[1] 是月初, dates[2] 是月底,但我们不假设如果我们这样做可能会简化。我们在下面生成了降序系列,但通常在 R 中使用升序。

下面的第一种方法使用每月序列和切割,下面的第二种方法使用每日序列。

没有使用任何包。

1) 我们定义了第一个月份的函数,fom,它给定一个日期或字符日期,使用 cut 给出月份的第一个日期。然后我们计算两个日期的第一个月份之间的每月日期,将其转换为月末,然后删除不严格位于日期中的日期之间的任何日期。

fom <- function(x) as.Date(cut(as.Date(x), "month"))

s <- seq(fom(dates[2]), fom(dates[1]), "-1 month")
ss <- fom(fom(s) + 32) - 1
ss[ss > dates[1] & ss < dates[2]]
## [1] "2019-05-31" "2019-04-30" "2019-03-31" "2019-02-28"

2) 另一种方法是在转换为 Date 类后计算两个日期元素之间的每日序列,然后仅保留第二天具有不同月份且在日期之间的那些在日期。这不使用剪切。

dt <- as.Date(dates)
s <- seq(dt[2], dt[1], "-1 day")
s[as.POSIXlt(s)$mon != as.POSIXlt(s+1)$mon & s > dt[1] & s < dt[2]]
## [1] "2019-05-31" "2019-04-30" "2019-03-31" "2019-02-28"

【讨论】:

  • 这就是我想要的,谢谢你的精彩解释。请解释为什么在此代码fom(fom(s) + 32) - 1中添加+32?
  • fom(s) 给出月初,加上 32 给出下个月的日期,然后 fom of that 给出该月的第一天。最后减去 1 得到 s 的最后一天。
  • 如果加上 32 给出一个 2 个月后的日期会发生什么,例如如果你从 1 月 31 日开始?
  • 这就是为什么我们在添加 32 之前取月初的原因。
【解决方案2】:

这里不需要删减:

library(lubridate)
dates <- c("2019-02-01", "2019-06-30")
seq(min(ymd(dates)), max(ymd(dates)), by = "months") - 1
#> [1] "2019-01-31" "2019-02-28" "2019-03-31" "2019-04-30" "2019-05-31"

reprex package (v2.0.1) 于 2021 年 11 月 25 日创建

【讨论】:

    猜你喜欢
    • 2017-08-10
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 2014-07-19
    • 2013-07-23
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多