pandas: Получить список месяцев между двумя датами
Есть DataFrame, в котором для каждого уникального id прогресса указана дата начала и дата окончания работы. Как из этой разницы начальной и конечной дат получить список месяцев, в которые выполнялась работа? Т.е. на выходе я хочу построить график, который покажет, сколько уникальных id пришлось на каждый месяц, при этом, если работа выполнялась несколько месяцев, она должна учитываться в каждый месяц.
progress_id month_start month_finish
0 e4897c239bcf0cbf7b081c8de86eb893 2018-04 NaT
1 81fb8b7412a483355d02d32987aaba6e 2018-06 2018-07
2 225784e4b9c1b3dcefc486f1e27f946b 2018-07 2019-01
3 c29cf5d7f832d3e82f99a118223eb729 2018-08 2018-08
4 b431e4ed2a994d9a8435553c52967ffe 2018-06 2018-09
Что пытался сделать, но так и не сообразил, как агрегировать в один столбцы с датами начала и конца: сделать unstack() по месяцам и заполнить месяца, в которые выполнялась работа единицами, остальное 0. Т.е. в строках - id, в столбах все месяцы от первого до последнего, на пересечении единицы между месяцем начала и месяцем конца.
Ответы (1 шт):
Можно попробовать сделать так:
df["month_finish"] = pd.to_datetime(df["month_finish"]) # приводим данные к нужному типу
df["month_start"] = pd.to_datetime(df["month_start"])
df = df.fillna(method="ffill", axis=1) # заполняем NaT значением, равным началу работ
ну и далее:
df["range"]=df.apply(lambda x: pd.date_range(x["month_start"],
x["month_finish"], freq="D"), axis=1)
# freq="D" нужна для того, чтобы поймать значения, где начало и конец работ равны
df["months"] = df["range"].apply(lambda x: set(x.month.to_list()))
ну и получаем df:
progress_id month_start month_finish \
0 e4897c239bcf0cbf7b081c8de86eb893 2018-04-01 2018-04-01
1 81fb8b7412a483355d02d32987aaba6e 2018-06-01 2018-07-01
2 225784e4b9c1b3dcefc486f1e27f946b 2018-07-01 2019-01-01
3 c29cf5d7f832d3e82f99a118223eb729 2018-08-01 2018-08-01
4 b431e4ed2a994d9a8435553c52967ffe 2018-06-01 2018-09-01
range months
0 DatetimeIndex(['2018-04-01'], dtype='datetime6... {4}
1 DatetimeIndex(['2018-06-01', '2018-06-02', '20... {6, 7}
2 DatetimeIndex(['2018-07-01', '2018-07-02', '20... {1, 7, 8, 9, 10, 11, 12}
3 DatetimeIndex(['2018-08-01'], dtype='datetime6... {8}
4 DatetimeIndex(['2018-06-01', '2018-06-02', '20... {8, 9, 6, 7}