Python и pandas на собеседовании: 20 задач для аналитика
Практический разбор задач по Python и pandas на собеседовании аналитика: фильтрация, groupby, merge, даты, пропуски, отладка и объяснение результата.
Содержание статьи
На Python-собеседовании аналитика обычно не ждут олимпиадный алгоритм. Проверяют, можете ли вы взять таблицу, понять её зерно, аккуратно преобразовать данные и объяснить, почему результат заслуживает доверия. Задачи на pandas часто выглядят коротко, но в них спрятаны дубли, пропуски, типы дат и неправильный знаменатель.
Коротко
Решайте задачу через маленькие проверяемые шаги: осмотр таблицы, нормализация типов, фильтр, агрегация, проверка. Не превращайте одну строку pandas в демонстрацию магии. Читаемый код и ясное объяснение обычно сильнее редкого метода, который вы не можете защитить.
- До расчёта проверьте shape, dtypes, пропуски и уникальность ключа.
- После merge проверьте количество строк и ожидаемую кардинальность.
- Для пользователей используйте
nunique, для событий — сначала опишите зерно. - Даты приводите к одному типу и сравнивайте полуинтервалами.
- Объясняйте не только что делает код, но и какой бизнес-вопрос он закрывает.
Как читать условие на Python
Перед кодом назовите объект результата. Если просят «выручку по пользователям», одна строка должна быть на user_id. Если просят «активность по дням», результат будет на day, а пользователь может встречаться в исходном наборе много раз. Эта фраза помогает выбрать groupby, nunique и порядок соединений.
Затем уточните, что делать с пропусками и дублями. Пропущенный channel — это unknown или ошибка источника? Две строки с одним order_id — повтор или позиции одного заказа? Без этих вопросов можно идеально написать код, который считает не то.
| Вопрос | Пример ответа |
|---|---|
| Что означает строка? | одна позиция заказа или один заказ |
| Какой ключ результата? | user_id и календарный месяц |
| Что считать событием? | только оплаченный заказ |
| Как обрабатывать NULL? | unknown для канала, ошибка для суммы |
| Как проверить результат? | сверить число заказов и сумму с источником |
Задачи 1–4: фильтры, условия и новые колонки
Базовые задачи просят оставить оплаченные заказы, выбрать пользователей из сегмента или создать флаг «новый покупатель». Важно помнить, что в pandas для нескольких условий нужны & и скобки, а сравнение дат должно выполняться после to_datetime. При создании колонки лучше использовать np.select или Series.where, если условия нужно читать как бизнес-правило.
На собеседовании покажите, что можете сохранить исходный DataFrame и создать отдельный срез. .copy() после фильтра делает намерение явным и уменьшает риск неожиданного изменения исходных данных.
orders['created_at'] = pd.to_datetime(orders['created_at'])
is_paid = orders['status'].eq('paid')
is_full_month = orders['created_at'].between(
'2026-07-01', '2026-07-31 23:59:59', inclusive='both'
)
july_paid = orders.loc[is_paid & is_full_month].copy()
july_paid['is_large_order'] = july_paid['amount'].ge(5000)Задачи 5–7: groupby, agg и pivot
Частый промпт: посчитать выручку, число заказов и покупателей по каналу и месяцу. Сначала запишите зерно результата. Затем используйте named aggregation, чтобы столбцы говорили сами за себя. count считает непустые значения в выбранной колонке, size — строки группы, nunique — уникальные сущности. Эти операции нельзя менять местами без понимания результата.
Pivot удобен для отчёта, но не всегда нужен для расчёта. Для проверки и дальнейших JOIN обычно проще оставить длинный формат: одна строка на месяц и канал. На интервью проговорите, зачем вам широкая таблица и как обработаете отсутствующую комбинацию.
summary = (orders.loc[orders['status'].eq('paid')]
.groupby(['month', 'channel'])
.agg(revenue=('amount', 'sum'),
orders=('order_id', 'nunique'),
buyers=('user_id', 'nunique'))
.reset_index())
summary['arpu'] = summary['revenue'] / summary['buyers']Задачи 8–10: merge и контроль размножения
Дана таблица users и таблица orders. Нужно добавить канал регистрации и посчитать выручку по каналам. До merge выясни, уникален ли user_id в users. Если там несколько записей на пользователя, соединение размножит заказы. Для критичных расчётов используйте validate='many_to_one': pandas остановит код, если справочник нарушает ожидаемый контракт.
После соединения проверьте число строк, долю unmatched и сумму денег до и после. Не исправляйте проблему через drop_duplicates() без понимания, какую строку оставляете. Дедупликация — это бизнес-правило, а не косметическая операция.
enriched = orders.merge(
users[['user_id', 'channel']],
on='user_id',
how='left',
validate='many_to_one',
indicator=True,
)
print(enriched['_merge'].value_counts())
print(enriched['amount'].sum(), orders['amount'].sum())Задачи 11–13: пропуски, дубли и типы
Интервьюер может показать таблицу, где amount содержит числа и строки, channel пустой у части пользователей, а order_id повторяется. Правильный ответ не начинается с fillna(0) для всех колонок. Сначала определите смысл. Нулевой discount может быть корректен, а неизвестный источник нельзя автоматически назвать органикой.
Для дублей покажите, как отличите повтор загрузки от нескольких позиций заказа. Для типов используйте to_numeric(errors="coerce"), но сразу посчитайте, сколько значений не распарсилось. Молчаливое превращение ошибки в NaN не является очисткой.
isna().mean()— доля пропусков по колонкам.duplicated(subset=[...])— проверка повторов по ожидаемому ключу.pd.to_numericиpd.to_datetime— явное приведение типов.value_counts(dropna=False)— увидеть неизвестные категории.- После очистки сохранить число удалённых или изменённых строк.
Задачи 14–16: даты и временные окна
Попросить месячную динамику или время до первой покупки — простой способ проверить, понимаете ли вы даты. Не группируйте строки по строковому created_at и не сравнивайте timestamps из разных таймзон. Создайте нормализованное поле, зафиксируйте границу периода и проверьте первые и последние значения.
Для retention можно получить cohort_day через groupby('user_id')['created_at'].transform('min'), но не называйте результат retention, пока не определил return event и горизонт. Python делает вычисление, а смысл всё равно задаётся аналитиком.
events['occurred_at'] = pd.to_datetime(events['occurred_at'], utc=True)
events['cohort_day'] = events.groupby('user_id')['occurred_at'].transform('min').dt.date
events['active_day'] = events['occurred_at'].dt.date
events['day_n'] = (
events['active_day'] - events['cohort_day']
).map(lambda delta: delta.days)
d7 = events.loc[events['day_n'].eq(7), 'user_id'].nunique()Задачи 17–18: apply, vectorization и сложное правило
Если условие можно выразить операциями над колонками, сначала выбирайте векторизацию. apply допустим, когда правило действительно построчное или требует нескольких полей и его нельзя ясно выразить маской. На собеседовании важно не повторять «apply всегда медленный», а объяснить масштаб и читаемость решения.
Сложное правило лучше вынести в именованную функцию и покрыть маленькими примерами. Проверьте обычную строку, пропуск, границу и неожиданный тип. Рабочий аналитик думает не только о том, как получить ответ сейчас, но и как коллега поймёт его через месяц.
Задачи 19–20: отладка и воспроизводимость
Покажите, как ищете ошибку в расчёте: уменьшаете данные до маленького примера, проверяете промежуточные формы и сравниваете с ручным ответом. Если график внезапно вырос вдвое, сначала проверьте merge и дубли, а не меняйте визуальный масштаб.
Для воспроизводимости зафиксируйте вход, версию библиотек, дату среза и порядок запуска. Ноутбук, который работает только после ручного запуска ячеек в случайном порядке, не является надёжным решением. Даже на собеседовании полезно сказать, какой тест или контрольный DataFrame вы добавите после расчёта.
«Я получил таблицу на уровне user_id и month. Теперь проверю уникальность ключа, сравню сумму с источником и отдельно посмотрю пользователей без channel. Если контроль проходит, результат можно отдавать в визуализацию».
Мини-кейс end-to-end: один DataFrame, три проверки
Возьмите таблицу событий и решите задачу «найти пользователей, которые активировались за 24 часа, а затем посчитать их D7». Сначала приведите occurred_at к UTC или бизнесовой таймзоне и зафиксируйте signup_at. Затем найдите первое meaningful action и вычислите активацию. После этого отдельным шагом проверьте активность на седьмой день. Не объединяйте всё в одну цепочку: промежуточные таблицы нужны для контроля.
Три проверки обязательны. Первая — один user_id имеет одну дату регистрации. Вторая — activation_at не раньше signup_at. Третья — D7 считается от всей когорты, а не только от активированных. Если ответ отличается от SQL-версии, сравните списки user_id на каждом шаге, а не только финальные проценты.
events['occurred_at'] = pd.to_datetime(events['occurred_at'], utc=True)
cohort = users[['user_id', 'signup_at']].drop_duplicates('user_id')
value = events[events['event_name'].eq('core_action')].merge(cohort, on='user_id')
value = value.loc[value['occurred_at'].ge(value['signup_at'])]
first_value = value.groupby('user_id')['occurred_at'].min()
activated = first_value.lt(cohort.set_index('user_id')['signup_at'] + pd.Timedelta('24h'))Какие ошибки в pandas замечают сразу
Красные флаги на собеседовании — inplace=True без объяснения, chained assignment, count() вместо nunique(), merge без validate, заполнение всех пропусков нулём и ручная работа со строковыми датами. Ни один из этих приёмов не запрещён навсегда, но кандидат должен понимать, когда они меняют результат или усложняют поддержку.
Не нужно произносить теорию на каждый метод. Достаточно коротко связать решение с риском: «Здесь использую nunique, потому что считаю пользователей, а не события»; «Добавляю validate, чтобы справочник не размножил строки»; «Сохраняю длинный формат, потому что дальше будет merge».
Как тренировать pandas без заучивания методов
Возьмите одну таблицу заказов и решите на ней десять разных вопросов: месячная выручка, первая покупка, повторная покупка, топ-категория, средний чек, пропуски канала, время до заказа, сегмент пользователей и сверка с SQL. Меняйте зерно результата и каждый раз записывайте контрольное число.
Полезно проговаривать метод в терминах результата: «groupby уменьшает таблицу до месяца и канала», «merge добавляет атрибут пользователя», «nunique считает людей, а не события». Тогда навыки переносятся на новый датасет и не зависят от того, встретилось ли в условии слово orders.
Материалы по теме

Нейросеть для Python: как писать и проверять код анализа
Как использовать нейросеть для Python и pandas: проверенный пример на 548 рейсах, пять ошибок с кодом до и после, тесты загрузки, merge, группировок и дат.

Pandas groupby и merge: как собрать аналитический отчёт из таблиц
Практический разбор groupby, merge и pivot_table в pandas: как агрегировать заказы, присоединять справочники и не посчитать выручку дважды.
Вопросы по SQL на собеседовании: 35 вопросов с короткими ответами
Теоретические вопросы по SQL для аналитика с ответами в два-пять предложений: ключи, NULL, JOIN, GROUP BY, окна, индексы, CTE, DAU и retention — с примерами на данных.