生成两年内每月最后一天的序列

发布于 2024-12-19 01:41:36 字数 873 浏览 3 评论 0原文

我使用 lubridate 并认为这会很容易

ymd("2010-01-31")+months(0:23)

,但看看会得到什么。一切都乱了!

 [1] "2010-01-31 UTC" "2010-03-03 UTC" "2010-03-31 UTC" "2010-05-01 UTC" "2010-05-31 UTC" "2010-07-01 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-10-01 UTC"
[10] "2010-10-31 UTC" "2010-12-01 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-03-03 UTC" "2011-03-31 UTC" "2011-05-01 UTC" "2011-05-31 UTC" "2011-07-01 UTC"
[19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-10-01 UTC" "2011-10-31 UTC" "2011-12-01 UTC" "2011-12-31 UTC"

然后我读到了 lubridate 如何迎合间隔、持续时间和周期等现象。所以,好吧,我意识到一个月实际上是由 (365*4+1)/48 = 30.438 天定义的天数。所以我试图变得聪明并将其重写为

ymd("2010-01-31")+ as.period(months(0:23))

但这只是给出了一个错误。

as.period.default(months(0:23)) 中的错误: 
  (列表)对象不能被强制输入“double”

I use lubridate and figured that this would be so easy

ymd("2010-01-31")+months(0:23)

But look what one gets. It is all messed up!

 [1] "2010-01-31 UTC" "2010-03-03 UTC" "2010-03-31 UTC" "2010-05-01 UTC" "2010-05-31 UTC" "2010-07-01 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-10-01 UTC"
[10] "2010-10-31 UTC" "2010-12-01 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-03-03 UTC" "2011-03-31 UTC" "2011-05-01 UTC" "2011-05-31 UTC" "2011-07-01 UTC"
[19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-10-01 UTC" "2011-10-31 UTC" "2011-12-01 UTC" "2011-12-31 UTC"

Then I read how lubridate caters to phenomenon such as interval, duration and period. So, OK I realize that a month is actually the number of days defined by (365*4+1)/48 = 30.438 days. So I tried to get smart and rewrite it as

ymd("2010-01-31")+ as.period(months(0:23))

But that just gave an error.

Error in as.period.default(months(0:23)) : 
  (list) object cannot be coerced to type 'double'

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

鱼窥荷 2024-12-26 01:41:36

是的,您找到了正确的技巧:从下个月的第一天返回一天。

这是基础 R 中的一行:

R> seq(as.Date("2010-02-01"), length=24, by="1 month") - 1
 [1] "2010-01-31" "2010-02-28" "2010-03-31" "2010-04-30" "2010-05-31"
 [6] "2010-06-30" "2010-07-31" "2010-08-31" "2010-09-30" "2010-10-31"
[11] "2010-11-30" "2010-12-31" "2011-01-31" "2011-02-28" "2011-03-31"
[16] "2011-04-30" "2011-05-31" "2011-06-30" "2011-07-31" "2011-08-31"
[21] "2011-09-30" "2011-10-31" "2011-11-30" "2011-12-31"
R> 

所以不需要 lubridate (虽然像这样的简单任务不需要(是一个很好的包)。另外,它对现有基本功能的重载仍然让我觉得有些危险......

Yes, you found the correct trick: going back a day from the first of the next month.

Here is as a one-liner in base R:

R> seq(as.Date("2010-02-01"), length=24, by="1 month") - 1
 [1] "2010-01-31" "2010-02-28" "2010-03-31" "2010-04-30" "2010-05-31"
 [6] "2010-06-30" "2010-07-31" "2010-08-31" "2010-09-30" "2010-10-31"
[11] "2010-11-30" "2010-12-31" "2011-01-31" "2011-02-28" "2011-03-31"
[16] "2011-04-30" "2011-05-31" "2011-06-30" "2011-07-31" "2011-08-31"
[21] "2011-09-30" "2011-10-31" "2011-11-30" "2011-12-31"
R> 

So no need for lubridate which (while being a fine package) isn't needed for simple task like this. Plus, its overloading of existing base functions still strikes me as somewhat dangerous...

拔了角的鹿 2024-12-26 01:41:36

令人惊奇的是,输入问题如何集中创造力。我想我找到了答案。我不妨将其发布在这里,供下一个发现自己在浪费时间的可怜灵魂。

ymd("2010-02-01")+ months(0:23)-days(1)

只需指定下个月的第一天并从中生成一个序列,但从中减去 1 天即可获得上个月的最后一天。

[1] "2010-01-31 UTC" "2010-02-28 UTC" "2010-03-31 UTC" "2010-04-30 UTC" "2010-05-31 UTC" "2010-06-30 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-09-30 UTC"
[10] "2010-10-31 UTC" "2010-11-30 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-02-28 UTC" "2011-03-31 UTC" "2011-04-30 UTC" "2011-05-31 UTC" "2011-06-30 UTC"
[19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-09-30 UTC" "2011-10-31 UTC" "2011-11-30 UTC" "2011-12-31 UTC"

顺便说一句,我如何摆脱讨厌的“UTC”名称。时区在需要时可以拯救生命。其余时间它们都是令人讨厌的。

It is amazing how typing out a question focuses creative energy. I think I worked out the answer. I may as well post it here for the next poor soul who finds themselves wasting time.

ymd("2010-02-01")+ months(0:23)-days(1)

Simply specify the first day of the next month and generate a sequence from that but subtract 1 days from it to get the last day of the preceding month.

[1] "2010-01-31 UTC" "2010-02-28 UTC" "2010-03-31 UTC" "2010-04-30 UTC" "2010-05-31 UTC" "2010-06-30 UTC" "2010-07-31 UTC" "2010-08-31 UTC" "2010-09-30 UTC"
[10] "2010-10-31 UTC" "2010-11-30 UTC" "2010-12-31 UTC" "2011-01-31 UTC" "2011-02-28 UTC" "2011-03-31 UTC" "2011-04-30 UTC" "2011-05-31 UTC" "2011-06-30 UTC"
[19] "2011-07-31 UTC" "2011-08-31 UTC" "2011-09-30 UTC" "2011-10-31 UTC" "2011-11-30 UTC" "2011-12-31 UTC"

By the way, how do I get rid of the pesky "UTC" designations. Time zones are a life saver when they are needed. The rest of the time they are a nuisance.

眼泪也成诗 2024-12-26 01:41:36

tidyverse 添加了 clock另外lubridate 包,它具有各种日期算术的良好功能。有几种方法可以回答这个问题:

library(clock)

# sequence first day of every month and then set day to be last day
seq(as.Date("2010-01-01"), by = "1 month", length.out = 24) |> set_day("last")

date_seq 将生成无效日期,例如“2010-02-31”,但您可以指定在这些情况下要执行的操作无效参数。在这种情况下,请返回到之前的有效日期。

start <- date_build(2010, 01, 31)
date_seq(start, by = duration_months(1), total_size = 24, invalid = "previous")

或者,您可以对月份进行排序,然后将最后一天添加回末尾:

start <- calendar_narrow(year_month_day(2010, 01, 01), "month") # [1] "2010-01"

seq(start, by = 1, length.out = 24) |>
  set_day("last") |>
  as.Date()

tidyverse has added the clock package in addition to the lubridate package that has nice functionality for various date arithmetic. There are a few ways you could answer this:

library(clock)

# sequence first day of every month and then set day to be last day
seq(as.Date("2010-01-01"), by = "1 month", length.out = 24) |> set_day("last")

date_seq will generate invalid dates such as "2010-02-31", but you can specify what to do in these instances with the invalid argument. In this case, go back to the previous valid date.

start <- date_build(2010, 01, 31)
date_seq(start, by = duration_months(1), total_size = 24, invalid = "previous")

Alternatively, you can sequence months and then add the last day back in at the end:

start <- calendar_narrow(year_month_day(2010, 01, 01), "month") # [1] "2010-01"

seq(start, by = 1, length.out = 24) |>
  set_day("last") |>
  as.Date()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文