rushi
rushi

Reputation: 333

how to randomly generate a date between a vector of start dates and end dates

i have a data frame of vectors of start dates and end dates:

start_date end_date ind
2/1/2023 2/15/2023 0
3/4/2023 4/17/2023 1
4/4/2023 4/31/2023 1

new data frame:

start_date end_date random_date
2/1/2023 2/15/2023 0
3/4/2023 4/17/2023 3/31/2023
4/4/2023 4/31/2023 4/30/2023

I'm looking for generate a random date for a vector for the rows that show an indicator

here is my attempt:

random_date <- as.Date(sample(as.numeric(df$start_date): as.numeric(df$end_date), 1, replace = T), origin = "1970-01-01")

Edited so I can get a time saving solution

Upvotes: 1

Views: 292

Answers (2)

Ma&#235;l
Ma&#235;l

Reputation: 52209

With map2_vec:

library(purrr)
library(dplyr)
df %>% 
  mutate(random_date = map2_vec(start_date, end_date, \(x, y) sample(seq.Date(x, y, by = "day"), 1)))

#  start_date   end_date random_date
#1 2023-02-01 2023-02-15  2023-02-01
#2 2023-03-04 2023-04-17  2023-04-08

Note that map2_vec was introduced in purrr 1.0.0. It is useful especially in this case, because mapply or previous purrr::map functions notoriously failed in returning a date object.


Before purrr 1.0.0, you can use map in combination with lubridate::as_date:

library(lubridate)
df %>% 
  mutate(random_date = as_date(map2_dbl(start_date, end_date, \(x, y) sample(seq.Date(x, y, by = "day"), 1))))

Upvotes: 0

JKupzig
JKupzig

Reputation: 1303

Here is another solution using seq and sample, as you've done in your provided attempt.

library(dplyr)

df <- data.frame(start_date = c("02/01/2023", "03/04/2023"), 
                 end_date = c("02/15/2023", "04/17/2023"))
df %>% 
  mutate(start_date = as.Date(start_date, format="%m/%d/%Y"),
         end_date = as.Date(end_date, format="%m/%d/%Y")) %>% 
  rowwise() %>% 
  mutate(random_date = (seq(start_date, end_date, by="days"))[sample(length(seq(start_date, end_date, by="days")), 1)])

Solution:
      start_date end_date   random_date
      <date>     <date>     <date>     
    1 2023-02-01 2023-02-15 2023-02-09 
    2 2023-03-04 2023-04-17 2023-03-31 

Upvotes: 0

Related Questions