R 中任意确定的开始和结束日期
Round date to arbitrary established start and end of the year in R
我正在寻找 快速 解决方案以将日期舍入到一年的最后一天,但年份从 1.10 开始到 30.09 结束。所以,当我有 2020-04-05 时,它应该将这个日期四舍五入到 2020-09-30。当我有 2020-12-12 时,它应该将该日期四舍五入为 2021-09-30。我试过这个功能:
round_date_to_seasons <- function(dates) {
rounded_dates <- structure(rep(NA_real_, length(dates)), class = "Date")
for (i in seq.int(1, length.out = length(dates))) {
if (month(dates[i]) %in% c(10, 11, 12)) {
year(dates[i]) <- year(dates[i]) + 1
month(dates[i]) <- 9
day(dates[i]) <- 30
} else {
month(dates[i]) <- 9
day(dates[i]) <- 30
}
rounded_dates[i] <- dates[i]
}
rounded_dates
}
但是速度很慢。如果我正确地进行了分析,则值分配很慢,因此上面代码中的第 7、8、9、11、12 和 14 行,但最后一行还不错。对于长度为 1000 万或更长的向量,我真的需要尽可能快的函数。
没有理由一步一步来,你可以使用向量化函数。
例如,这会快很多:
library(lubridate)
round_date_to_seasons_new <- function(dates)
{
as.Date(ifelse(month(dates) %in% 10:12,
as_date(ISOdate(year(dates) + 1, 9, 30)),
as_date(ISOdate(year(dates), 10, 1))),
origin = '1970-01-01')
}
我相信这可以进一步改进,但是当 运行 在这里时,它至少快了一个数量级。
尽可能在 R 中使用矢量化函数。
在您的示例中,在循环的每次迭代中,都会检索整个 rounded_dates
-对象(多次),更改一个元素,然后将所有内容写回内存。
如果您的函数对整个对象执行某些操作,则这是必需的。但在这种情况下,第一次迭代只查看和更改第一个元素,第二次迭代仅查看和更改第二个元素,依此类推。
如果你使用向量化函数,R 知道它应该只看一小部分,最后只合并结果。
尝试:
library(lubridate)
round_date_to_seasons <- function(dat){
lubridate::ceiling_date(dat %m+% months(-9) + days(1),'year') %m+% months(9)-days(1)}
round_date_to_seasons(as.POSIXct('2020-04-05'))
[1] "2020-09-30 CEST"
round_date_to_seasons(as.POSIXct('2020-12-12'))
[1] "2021-09-30 CEST"
我正在寻找 快速 解决方案以将日期舍入到一年的最后一天,但年份从 1.10 开始到 30.09 结束。所以,当我有 2020-04-05 时,它应该将这个日期四舍五入到 2020-09-30。当我有 2020-12-12 时,它应该将该日期四舍五入为 2021-09-30。我试过这个功能:
round_date_to_seasons <- function(dates) {
rounded_dates <- structure(rep(NA_real_, length(dates)), class = "Date")
for (i in seq.int(1, length.out = length(dates))) {
if (month(dates[i]) %in% c(10, 11, 12)) {
year(dates[i]) <- year(dates[i]) + 1
month(dates[i]) <- 9
day(dates[i]) <- 30
} else {
month(dates[i]) <- 9
day(dates[i]) <- 30
}
rounded_dates[i] <- dates[i]
}
rounded_dates
}
但是速度很慢。如果我正确地进行了分析,则值分配很慢,因此上面代码中的第 7、8、9、11、12 和 14 行,但最后一行还不错。对于长度为 1000 万或更长的向量,我真的需要尽可能快的函数。
没有理由一步一步来,你可以使用向量化函数。
例如,这会快很多:
library(lubridate)
round_date_to_seasons_new <- function(dates)
{
as.Date(ifelse(month(dates) %in% 10:12,
as_date(ISOdate(year(dates) + 1, 9, 30)),
as_date(ISOdate(year(dates), 10, 1))),
origin = '1970-01-01')
}
我相信这可以进一步改进,但是当 运行 在这里时,它至少快了一个数量级。
尽可能在 R 中使用矢量化函数。
在您的示例中,在循环的每次迭代中,都会检索整个 rounded_dates
-对象(多次),更改一个元素,然后将所有内容写回内存。
如果您的函数对整个对象执行某些操作,则这是必需的。但在这种情况下,第一次迭代只查看和更改第一个元素,第二次迭代仅查看和更改第二个元素,依此类推。
如果你使用向量化函数,R 知道它应该只看一小部分,最后只合并结果。
尝试:
library(lubridate)
round_date_to_seasons <- function(dat){
lubridate::ceiling_date(dat %m+% months(-9) + days(1),'year') %m+% months(9)-days(1)}
round_date_to_seasons(as.POSIXct('2020-04-05'))
[1] "2020-09-30 CEST"
round_date_to_seasons(as.POSIXct('2020-12-12'))
[1] "2021-09-30 CEST"