Datetime в Pandas: шпаргалка для собеседования
Зачем аналитику datetime в pandas
Временные ряды — главный формат данных в аналитике. DAU, MoM, cohort retention, скользящие средние — всё работает через datetime. На собесе проверяют знание dt-аксессора и resample.
Преобразование в datetime
import pandas as pd
# Из строки
df['date'] = pd.to_datetime(df['date'])
df['date'] = pd.to_datetime(df['date'], format='%d.%m.%Y')
# Из unix timestamp
df['ts'] = pd.to_datetime(df['ts_seconds'], unit='s')
# С обработкой ошибок
df['date'] = pd.to_datetime(df['date'], errors='coerce') # ошибки → NaTНа собесе: errors='coerce' — важный параметр, превращает некорректные в NaT вместо исключения.
dt-аксессор
# Компоненты
df['date'].dt.year
df['date'].dt.month
df['date'].dt.day
df['date'].dt.hour
df['date'].dt.dayofweek # 0=понедельник
df['date'].dt.day_name() # 'Monday'
df['date'].dt.quarter
df['date'].dt.is_month_end
df['date'].dt.is_weekend # pandas 2.0+
# Формат
df['date'].dt.strftime('%Y-%m-%d')
df['date'].dt.date # просто дата (без времени)
df['date'].dt.normalize() # обнулить времяСравнение и фильтрация
# За последние 30 дней
df[df['date'] >= pd.Timestamp.now() - pd.Timedelta(days=30)]
# В диапазоне
df[(df['date'] >= '2026-01-01') & (df['date'] < '2026-02-01')]
# По месяцу/году
df[df['date'].dt.year == 2026]
df[df['date'].dt.month == 4]
# Текущая неделя
df[df['date'].dt.isocalendar().week == pd.Timestamp.now().isocalendar().week]resample — ресэмплинг времени
# Нужен datetime как индекс
df = df.set_index('date')
# Агрегация по дням
df['amount'].resample('D').sum()
# По неделям (с понедельника)
df['amount'].resample('W-MON').sum()
# По месяцам
df['amount'].resample('M').sum()
# Даунсэмплинг с несколькими агрегатами
df.resample('W').agg({'amount': 'sum', 'user_id': 'nunique'})
# Апсэмплинг (из часов в минуты) + forward fill
df.resample('1min').ffill()Попробовать силы на подобных вопросах проще всего в тренажёре Карьерник — прямо в Telegram, без регистрации через сайт.
rolling — скользящие окна
# Скользящее среднее за 7 дней
df['ma_7d'] = df['amount'].rolling(window=7).mean()
# Скользящая сумма
df['sum_30d'] = df['amount'].rolling(window=30).sum()
# С условием min_periods
df['ma_7d'] = df['amount'].rolling(window=7, min_periods=1).mean()
# По времени (нужен datetime index)
df['ma_24h'] = df.set_index('date')['amount'].rolling('24h').mean()expanding — нарастающие агрегаты
# Нарастающий итог
df['cumsum'] = df['amount'].cumsum()
# Нарастающее среднее
df['cummean'] = df['amount'].expanding().mean()Timezone
# Локализовать (добавить timezone)
df['date'] = df['date'].dt.tz_localize('UTC')
# Конвертировать
df['moscow'] = df['date'].dt.tz_convert('Europe/Moscow')
# Убрать timezone
df['date'].dt.tz_localize(None)Ловушка: tz_localize нельзя применить дважды — сначала localize, потом convert.
Арифметика дат
# Добавить/вычесть
df['date_plus_7'] = df['date'] + pd.Timedelta(days=7)
df['date_minus_month'] = df['date'] - pd.DateOffset(months=1)
# Разница
(df['end'] - df['start']).dt.days
(df['end'] - df['start']).dt.total_seconds() / 3600 # в часах
# Возраст в днях
(pd.Timestamp.now() - df['registered_at']).dt.daysВажно: Timedelta — точный интервал (days=30 = ровно 30×24ч). DateOffset — календарный (months=1 = «через месяц», учитывает разную длину месяцев).
Генерация последовательностей
# Календарь
pd.date_range('2026-01-01', '2026-12-31', freq='D')
pd.date_range('2026-01-01', periods=12, freq='M')
# Рабочие дни
pd.bdate_range('2026-04-01', '2026-04-30')
# Каждую вторую неделю
pd.date_range('2026-01-01', periods=26, freq='2W')Пройти 30–50 задач по теме за вечер можно в Telegram-тренажёре. Это то, что отличает «знаю» от «уверенно отвечу на собесе».
Когортный анализ
# Месяц регистрации
df['cohort'] = df.groupby('user_id')['date'].transform('min').dt.to_period('M')
# Период активности
df['period'] = df['date'].dt.to_period('M')
# Месяцев с регистрации
df['cohort_idx'] = (df['period'] - df['cohort']).apply(lambda x: x.n)
# Когортная таблица
cohort_table = df.groupby(['cohort', 'cohort_idx'])['user_id'].nunique().unstack()10 задач с собесов
1. Выручка по месяцам
df.set_index('date')['amount'].resample('M').sum()2. MoM growth
monthly = df.set_index('date')['amount'].resample('M').sum()
mom = monthly.pct_change() * 1003. DAU за апрель
april = df[df['date'].dt.month == 4]
april.groupby(april['date'].dt.date)['user_id'].nunique()4. Скользящее среднее DAU за 7 дней
dau = df.groupby(df['date'].dt.date)['user_id'].nunique()
dau.rolling(7).mean()5. Доля заказов в выходные
df['is_weekend'] = df['date'].dt.dayofweek >= 5
df['is_weekend'].mean()6. Возраст пользователя в днях на момент покупки
(df['order_date'] - df['registered_at']).dt.days7. Конвертация в московское время
df['date_msk'] = df['date'].dt.tz_localize('UTC').dt.tz_convert('Europe/Moscow')8. Заказы по дням недели
df.groupby(df['date'].dt.day_name())['amount'].sum()9. Retention D7
df['signup'] = df.groupby('user_id')['date'].transform('min').dt.date
df['days_since'] = (df['date'].dt.date - df['signup']).dt.days
d7_users = df[df['days_since'] == 7]['user_id'].nunique()
cohort = df[df['days_since'] == 0]['user_id'].nunique()
retention_d7 = d7_users / cohort10. Заполнить пропущенные дни нулями
df.set_index('date').resample('D')['amount'].sum().fillna(0)Как тренироваться
Datetime в pandas — это не теория, а привычка. Dt-аксессор, resample, rolling — пишите каждый день, и через месяц они будут «в пальцах».
Тренажёр Карьерник содержит задачи на datetime: от dt-аксессора до timezone и когорт. С разборами типичных ловушек.
Совет: если колонка-дата в строковом формате — первое же действие pd.to_datetime. Не пытайтесь работать через str, это всегда заканчивается плохо.
Читайте также
FAQ
Timedelta vs DateOffset — что использовать?
Timedelta — точные интервалы (дни, часы, минуты). DateOffset — календарные (месяц, квартал, год). Для «ровно 30 дней» — Timedelta. Для «через месяц» — DateOffset.
Почему pandas тормозит на datetime-фильтрации?
Если колонка в string — каждое сравнение парсится заново. Превратите через to_datetime один раз в начале — и всё быстро.
to_datetime против astype('datetime64')
Функционально одинаково в современном pandas. to_datetime поддерживает format, errors, unit — безопаснее. astype меньше контроля.
Период (Period) vs Timestamp?
Timestamp — точка во времени (2026-04-15 14:30). Period — интервал (April 2026, 2026-Q1). Period удобен для когорт и resample.