I'm working with a dataset of 1,3M rows and 4 columns, 1 row per policy and for each a starting date and an end date.
My objective is to determine how many active policies I get per month, meaning within each time interval [deb;fin], how many obs for each month of the interval. 
Using tidyverse, I managed to create the following code, which is efficient on small datasets, but take almost 50 min to run on the input datasets described above.
Any advice to optimize expand > pivot_wider process ? Or maybe I'm not doing it the right way ? Thank you very much for your ideas !
library(tidyverse)
library(lubridate)
n <- 200
df <- data.frame(id = (1:n),
deb = sample(seq(as.Date('2020/01/01'), as.Date('2020/04/01'), by="day"), n, replace = T),
fin = sample(seq(as.Date('2020/05/01'), as.Date('2020/07/01'), by="day"), n, replace = T)
)
system.time((df2 <- df %>%
select(id, deb, fin) %>%
group_by(id, deb, fin) %>%
expand(dtmonth = format(seq.Date(floor_date(deb, "month"),
ceiling_date(fin, "month")-1,
by = "month"), "%Y-%m")) %>%
mutate(nb = 1) %>%
pivot_wider(names_from = dtmonth, values_from = nb)))