Собесов

Сценарий: resample временного ряда в pandas

PythonPandas базовый workflowСредняяMiddle

Условие

Дан минутный лог запросов requests(ts, user_id, status). Нужно получить:

  1. Число запросов и долю успешных по часам.
  2. Скользящее среднее по 24 часам.
  3. Перевести часовой ряд в дневной с агрегацией.

Решение

Подход

resample работает только если индекс — DatetimeIndex (или передан on= с datetime-колонкой). Алиасы: 'H' (час), 'D' (день), 'W-MON' (неделя с понедельника), 'M' (конец месяца), 'MS' (начало).

Реализация

import pandas as pd
 
df = df.set_index('ts').sort_index()
 
# Час
hourly = df.resample('H').agg(
    n_requests=('user_id', 'size'),
    n_success=('status', lambda s: (s == 200).sum()),
)
hourly['success_rate'] = hourly['n_success'] / hourly['n_requests']
 
# Скользящее среднее по 24 часам (24 точки)
hourly['ma_24h'] = hourly['n_requests'].rolling(window=24, min_periods=1).mean()
 
# Перевод в дневной
daily = hourly['n_requests'].resample('D').sum()

Обработка дыр

# Если в каком-то часу 0 запросов — resample не создаст строку?
# Создаст: resample заполняет полную сетку. Но если у вас НЕТ ts в этом часе,
# resample('H').size() даст 0, а не NaN. С агрегацией mean — NaN.
 
hourly = hourly.fillna({'n_requests': 0, 'n_success': 0})
hourly['success_rate'] = hourly['success_rate'].fillna(0)

Подводные камни

  1. Таймзоны: resample('D') на UTC-индексе даст UTC-сутки. Для «московских суток» сначала tz_convert('Europe/Moscow'), потом resample.
  2. 'M' — конец месяца, 'MS' — начало. Путаница ломает join по месяцу.
  3. rolling(24) без min_periods оставит NaN на первых 23 точках — для plot лучше min_periods=1.
  4. resample('W') агрегирует по неделям, кончающимся в воскресенье — для понедельника 'W-MON'.
  5. На очень редком ряду resample создаст много пустых периодов — для разреженных событий используйте groupby(pd.Grouper(freq=...)) с фильтром.

Эталонный ответ

df.set_index('ts').resample('H').agg(...) + .rolling(24).mean() для гладких графиков; следить за таймзоной и алиасами M/MS/W-MON.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти