Вы можете создать вектор всех целевых дат и выборку из него. Для создания вектора существует seq.Date
, метод seq
для объектов класса "Date"
.
start <- as.Date("2008-01-01")
end <- as.Date("2010-12-31")
s <- seq(start, end, by = "days")
Вектор s
включает все дни между start
и end
. Теперь сэмпл из него.
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
и немного сложнее. Тесты показывают, что функция f2
в два раза быстрее, чем f1
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)