Последнее известное значение: ограничиваем ffill внутри устройства
Датчик передаёт температуру не на каждом шаге. Для промежуточных строк решили использовать последнее значение. Один ffill по всей таблице перенёс температуру первого устройства второму. Даже внутри устройства надо определить, сколько пропусков разрешено заполнить.
Определить смысл переноса
ffill предполагает, что последнее известное состояние действует до следующего наблюдения. Для статуса устройства это бывает естественно, для температуры — приближение. Для отдельных операций правило уже неверно: последняя оплата не становится новой оплатой на каждом шаге.
Перенос идёт внутри объекта по времени. Сначала сортируют устройство и момент, затем группируют. Начальный пропуск группы остаётся неизвестным: предыдущего значения ещё нет.
Ограничить число продолженных шагов
limit задаёт число последовательных заполненных строк, а не длительность. В примере есть равномерная минутная сетка, и разрешён один пропуск после реального наблюдения. Для нерегулярного потока такое ограничение требует другой проверки.
Сохраняем исходное поле и восстановленное, затем отмечаем строки, полученные переносом. Это позволяет сравнить реальное покрытие и долю восстановлений.
import pandas as pd
x = pd.DataFrame({"device": ["A", "A", "A", "B", "B"],
"time": ["10:00", "10:01", "10:02", "10:00", "10:01"],
"value": [20.0, None, None, None, 30.0]})
x["time"] = pd.to_datetime("2026-10-01 " + x["time"], format="%Y-%m-%d %H:%M")
x = x.sort_values(["device", "time"])
x["filled"] = x.groupby("device")["value"].ffill(limit=1)
x["restored"] = x["value"].isna() & x["filled"].notna()
print(x.to_string(index=False))
assert x.loc[1, "filled"] == 20
assert pd.isna(x.loc[2, "filled"]) and pd.isna(x.loc[3, "filled"])
assert x["restored"].sum() == 1Восстановлена минута 10:01 у A. Следующий пропуск остаётся неизвестным, а B не получает чужую температуру. Проверка включает начальный пропуск другой группы — случай, который теряется в примере с одним устройством.
Перейти к ограничению по времени
При нерегулярных событиях переносите также момент последнего реального наблюдения. Вычисляйте возраст и оставляйте результат лишь до разрешённого срока. limit=3 способен означать секунды для одного устройства и дни для другого.
При известном расписании сначала постройте ожидаемую сетку. Она показывает полностью отсутствующие строки, а не только NaN в существующих. Расписание должно соответствовать устройству: ночные минуты для дневного прибора создадут искусственные пропуски.
До заполнения проверьте уникальность пары устройства и времени. Два разных показания одного момента требуют выбора версии или агрегации. Порядок исходного файла не должен определять значение, которое будет перенесено дальше.
Если восстановленные строки участвуют в среднем за период, они меняют веса состояний. Для нерегулярных замеров среднее по строкам не равно среднему по времени. Сохранённый restored помогает понять, какая часть результата опирается на реальные наблюдения и где изменение политики восстановления меняет вывод.
Закрепить на практике
Начните с бесплатного урока обработки пропусков. После базовых задач используйте пример статьи, чтобы проверить границы групп, начальные пропуски и допустимую длину переноса. Откройте бесплатный урок и задачи. Полная последовательность тем — в бесплатном курсе.
Продолжить на практике
- NumPy и pandas: практический тренажёр ↗
Бесплатный тренажёр NumPy и pandas для тех, кто знает основы Python. Научитесь очищать таблицы, объединять данные и собирать отчёты: 31 урок и 124 задачи с кодом и автоматической проверкой.
