First, like I mentioned above, your dates aren't actually dates—they're factors that you'll need to convert.
I'm not well-versed in the imputation packages—other folks might have ideas with those—but that might be overkill for a simple example like this anyway. Assign groups based on whether the date is already present, then count along those groups and use that as an offset of how many months to add on.
Your actual output can be more concise: you don't necessarily need to keep the group column, and you probably want to overwrite the date column, whereas for presentation I've put the filled in dates in a separate column.
library(dplyr)
library(lubridate)
dates %>%
mutate(dates = as.Date(dates),
group = cumsum(!is.na(dates))) %>%
group_by(group) %>%
tidyr::fill(dates) %>%
mutate(filled = dates + months(seq_along(dates) - 1))
#> # A tibble: 10 x 3
#> # Groups: group [3]
#> dates group filled
#> <date> <int> <date>
#> 1 2019-02-01 1 2019-02-01
#> 2 2019-02-01 1 2019-03-01
#> 3 2019-02-01 1 2019-04-01
#> 4 2019-02-01 1 2019-05-01
#> 5 2019-02-01 1 2019-06-01
#> 6 2019-02-05 2 2019-02-05
#> 7 2019-02-05 2 2019-03-05
#> 8 2019-02-05 2 2019-04-05
#> 9 2019-02-05 2 2019-05-05
#> 10 2019-02-09 3 2019-02-09
Edited to add: I toyed with a second method where you instead count by how many observations each date has, then make a list-column of your sequence, and unnest it. I don't think it's better, and it's more convoluted (especially from having to essentially group_by
twice), but maybe there's a use-case for it.
dates %>%
mutate(dates = as.Date(dates)) %>%
tidyr::fill(dates) %>%
count(dates) %>%
group_by(dates) %>%
mutate(filled = list(seq.Date(from = dates, by = "1 month", length.out = n))) %>%
tidyr::unnest(filled)
# same output as above