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.