将日期转换为数字但限制为一年中的天数

Converting date to numeric but limiting to number of days in year

我想在 2008-01-01 和 2010-12-31 之间创建大约 10K 个日期对象。我为此编写了代码,但实际上我想在 2008 年保留 1-366 天,因为 2008-02-29(闰年)我希望它们在 366 之后重新启动,然后在 2009-01-01 变为 1。我可以只为 2008 年然后 2009 年然后 2010 年创建,但这并不方便。我正在阅读有关 lubridate 的内容,但无法弄清楚。我也可以过滤 1 到 366,然后过滤 367-731,但这也不会有效。有人知道更好的方法吗?

    set.seed(123)
    tim1=sample(365*3+1,10000,replace = TRUE)   ### that plus 1 from feb 29 in 2008
    dat1=as.Date(tim1,origin="2007-12-31")   # then 1 will be 2008-01-01

您可以创建一个包含所有目标日期的向量并从中抽样。要创建矢量,有 seq.Dateseq 对象的方法 class "Date"

start <- as.Date("2008-01-01")
end <- as.Date("2010-12-31")
s <- seq(start, end, by = "days")

矢量 s 包括 startend 之间的所有日期。现在从中取样。

set.seed(123)
dat1 <- sample(s, 10000, TRUE)

将示例转换为一年中的某一天。参见 help("strptime")

as.numeric(format(dat1, format = "%j"))

最后,删除s,不再需要了。

rm(s)    # tidy up

编辑。

以下两个函数执行问题要求的操作,但使用两种不同的方法。
f1 是上面包裹在函数中的代码,f2 使用 ave/seq_along/match 并且有点复杂。测试显示函数 f2f1

快两倍
f1 <- function(start_date, end_date, n){
  start <- as.Date(start_date)
  end <- as.Date(end_date)
  s <- seq(start, end, by = "days")
  y <- sample(s, n, replace = TRUE)
  as.numeric(format(y, format = "%j"))
}

f2 <- function(start_date, end_date, n){
  start <- as.Date(start_date)
  end <- as.Date(end_date)
  s <- seq(start, end, by = "days")
  y <- sample(s, n, replace = TRUE)
  z <- ave(as.integer(s), lubridate::year(s), FUN = seq_along)
  z[match(y, s)]
}

set.seed(123)
x1 <- f1("2008-01-01", "2010-12-31", 100)
set.seed(123)
x2 <- f2("2008-01-01", "2010-12-31", 100)

all.equal(x1, x2)
#[1] TRUE

现在开始测试。

library(microbenchmark)

mb <- microbenchmark(
  f1 = f1("2008-01-01", "2010-12-31", 1e4),
  f2 = f2("2008-01-01", "2010-12-31", 1e4),
  times = 50
)
print(mb, order = "median")

ggplot2::autoplot(mb)