2025, Dec 24 03:02
Заполнение пропусков дат события в pandas по среднему сдвигу
Пошаговое решение в pandas: считаем средний сдвиг между therapy_dt и incident_dt и заполняем только пропуски с помощью update(overwrite=False). Пример и код.
Восполнение дат события на основе надежных меток лечения — распространенная задача в EDA и регрессионных workflow, особенно когда в поле события есть пропуски. Если оба столбца уже приведены к pandas datetime и вы посчитали средний интервал между ними, можно заполнить только отсутствующие значения, не трогая корректные записи.
Постановка задачи
Есть два столбца с датами: один — с датой события, где возможны пропуски; второй — с датой лечения, которая считается точной. Нужно вычислить среднюю разницу во времени между лечением и событием по строкам, где обе даты присутствуют, а затем использовать эту среднюю величину, чтобы заполнить недостающие даты события, не изменяя уже заданные.
Минимальный пример
Небольшой датафрейм с несколькими пропусками в датах события:
>>> tbl
incident_dt therapy_dt
0 2025-02-20 2025-04-29
1 NaT 2025-05-22
2 NaT 2025-05-27
3 2025-03-14 2025-04-26
4 NaT 2025-05-11
5 2025-02-16 2025-04-23
6 NaT 2025-05-04
7 NaT 2025-05-20
8 2025-03-18 2025-05-28
9 2025-02-22 2025-05-21
Что происходит и почему это важно
В наборе данных смешаны полные строки и строки без даты события. Удалять их не хочется, потому что столбец важен для анализа. Лучше вычислить средний временной сдвиг по строкам, где обе даты есть, и затем последовательно применить его, заполняя только пропуски. В pandas это делается векторно и позволяет сохранить исходные значения, обрабатывая тысячи строк сразу.
Решение
Сначала посчитайте среднюю разницу по строкам, где обе даты заданы. Затем создайте рабочую копию этих двух столбцов, проставьте в ней дату события как дату лечения плюс средний сдвиг и верните заполненные значения в исходный датафрейм, обновив только пропуски.
>>> subset = tbl[tbl["incident_dt"].notna()]
>>> mean_delta = (subset["therapy_dt"] - subset["incident_dt"]).mean().round('d')
>>> mean_delta
Timedelta('67 days 00:00:00')
>>> tmp = tbl[["incident_dt", "therapy_dt"]].copy()
>>> tmp["incident_dt"] = tmp["therapy_dt"] + mean_delta
>>> tbl.update(tmp, overwrite=False)
>>> tbl
incident_dt therapy_dt
0 2025-02-20 2025-04-29
1 2025-07-28 2025-05-22
2 2025-08-02 2025-05-27
3 2025-03-14 2025-04-26
4 2025-07-17 2025-05-11
5 2025-02-16 2025-04-23
6 2025-07-10 2025-05-04
7 2025-07-26 2025-05-20
8 2025-03-18 2025-05-28
9 2025-02-22 2025-05-21
Ключевой момент — вызов update с параметром overwrite=False. Он гарантирует, что существующие непропущенные значения incident_dt останутся как есть, а значения NaT будут заполнены из копии. Вызов round('d') приводит средний сдвиг к целому числу дней.
Почему это полезно
Этот подход даёт простой и воспроизводимый шаг импутации, который органично вписывается в последующий EDA и регрессионное моделирование. Он опирается только на информацию из вашего набора данных и не трогает корректные значения, что помогает сохранить целостность уже проверенных данных.
Выводы
Вычислите средний временной сдвиг по строкам с обеими датами, примените его в копии, чтобы получить кандидатные значения, и используйте update с отключённым overwrite, чтобы заполнить только пропуски. Такой шаблон краток, бережно относится к исходным данным и органично вписывается в рабочий процесс анализа на pandas.