Блог Stepik про учебу и карьеру

Python-собеседование для аналитика данных: как подготовиться, чтобы получить оффер

Перед тем, как идти на собеседование, кандидату стоит понять, какие существуют этапы интервью у аналитиков и какое место в них занимает Python.

Структура собеседований на Data-, BI- или Продуктового аналитика выглядит так:

  1. Скрининг с HR
  2. Техническое собеседование на знание SQL, Python
  3. *Продуктовое интервью на знание метрик, статистики и знание A/B-тестов
  4. Финальное интервью с командой

* - этап спрашивают у продуктовых аналитиков
Иногда 2 и 3 пункт меняют местами или объединяют в один. В любом случае видим, что знание Python позволяет доходить до финальных этапов и получать оффер. А теперь немного углубимся в этапы:

Скрининг с HR

На скрининге задают вопросы уровня: “Используешь ли Python в работе?”. Если да, то в каких задачах? Конкретные навыки тут не проверяют в отличии от SQL, в котором теоретические вопросы могут спрашивать даже на скрининге.

Также HR часто подсказывают кандидатам, что будет на следующем этапе: стоит ли ждать задачку по Python или нет и даже могут поделиться направленностью задач : будет Pandas или задачи уровня изи LeetCode

Техническое интервью

На этом этапе проверяют умение решать задачки. Python занимает до 30% времени среди вопросов интервьюеров. Связано это с тем, что на технический собес выделяют до 1.5 часов. За это время нужно успеть познакомиться, проверить, умеет ли человек писать SQL, знает ли он статистику. Итого, по остаточному принципу остается 10-30 минут на проверку знаний по Python

Что можно успеть проверить за 10-30 минут? Можно дать задачку и понять, знает ли кандидат базовый синтаксис и умеет ли он работать с таблицами в Pandas. Отсюда рождается 2 блока задач, которые спрашивают на интервью: базовый синтаксис и Pandas.
Совет: если у вас осталось мало времени перед собеседованиями, советуем готовиться именно к Pandas, так как встречается он гораздо чаще. Связано это с тем, что аналитикам необходимо уметь работать с табличками и с помощью них быстро отвечать на вопросы бизнеса.

Pandas

Подготовку к Pandas можно разделить на несколько тем:

  1. Как читать таблицу из разных источников
  2. Как фильтровать данные

После них можно приступить к более продвинутым темам:

  1. Лямбда-функции
  2. Сортировка данных
  3. Группировка
  4. Создание сводных таблиц
Ниже рассмотрим примеры на приложенных наборах данных: melb_data_fe.csv и архиве movies_data.zip. Будет здорово, если вы тоже скачаете эти датасеты и позапускаете ячейки кода, приведенные в статье. Скачать их можно по ссылке

Чтение таблиц из разных источников

В реальной жизни данные редко приходят в виде уже готового дата-фрейма и поэтому их для начала нужно подготовить. Здесь вы должны знать о том, как прочитать данные из основных форматов. Полезно будет ознакомиться с методами чтения CSV, Excel, SQL-таблиц, а также попробовать импорт файла по URL.

Для наших дальнейших манипуляций потребуется запустить следующий код:
import pandas as pd
from zipfile import ZipFile

melb_fe = pd.read_csv("melb_data_fe.csv")

with ZipFile("movies_data.zip") as z:
    movies = pd.read_csv(z.open("movies.csv"))
    ratings1 = pd.read_csv(z.open("ratings1.csv"))
    ratings2 = pd.read_csv(z.open("ratings2.csv"))
    dates = pd.read_csv(z.open("dates.csv"))

dates["date"] = pd.to_datetime(dates["date"])

Фильтрация данных

Что могут спросить.
Как правило вопрос формулируется так: выберите клиентов или сессии пользователей, которые удовлетворяют какому-то условию

Для этого в Pandas существуют булевы маски, которые получают на вход условие над дата-фреймом, а возвращают True или False
Например, стоимость больше 100 тысяч мы запишем, как df[‘Price'] > 100000. А чтобы отобрать нужные строки, фильтр мы подадим внутри скобок дата фрейма по шаблону df[условие], например, df[df[‘Price'] > 100000] - так мы получим все строки датасета, соответствующие условию нашего фильтра.
Практические примеры
1.Найдём количество трёхкомнатных квартир в городе Мельбурн:
melb_fe[melb_fe['Rooms'] == 3].shape[0]
# 5881
2. А теперь уточним наш поиск. Отберём трёхкомнатные квартиры дешевле 300 тысяч
melb_fe[(melb_fe['Rooms'] == 3) & (melb_fe['Price'] < 300000)].shape[0]
# 3
Важно помнить, что в комбинированных условиях следует использовать логические операторы & (И) и | (ИЛИ). Использование операторов and и or приведёт к ошибке
3. Не стоит забывать и о том, что мы можем сочетать фильтрацию со статистическими методами.

Давайте выясним медианную площадь для тех объектов, стоимость которых выше средней по нашему набору данных:
# считаем среднюю цену за объект
mean_price = melb_fe['Price'].mean()
# вычисляем медианную площадь среди тех объектов, которые соответствуют условию
melb_fe[melb_fe['Price'] > mean_price]['BuildingArea'].median()
# 126.0
Как готовиться: советуем брать таблицу и задавать вопросы к данным, отрабатывая нужные функции. Кстати в нашем курсе есть отдельный разбор этого датасета, рекомендуем ознакомиться - урок 8.5

Lambda-функции

Что могут спросить: создать расчет метрики используя лямбду, например, для CTR или конверсии
Пример 1. Сделаем скидку для столбца 'Price' в нашем датасете недвижимости
melb_fe['discounted_price'] = melb_fe['Price'].apply(lambda x: x * 0.9)
melb_fe
Пример 2. Посчитаем метрику CTR
df = pd.DataFrame({
    'campaign': ['Яндекс.Директ', 'Google Ads', 'VK Реклама'],
    'clicks': [150, 0, 45],
    'impressions': [5000, 0, 1200]
})
df['CTR'] = df.apply(lambda row: row['clicks'] / row['impressions'] if row['impressions'] > 0 else 0, axis=1)
df['CTR_percent'] = df['CTR'].apply(lambda x: round(x * 100, 2))
df
Рекомендации по подготовке
Запомните разницу:
  • .apply(lambda x: ...) — вызывается для конкретного столбца дата-фрейма и работает по значениям только этого столбца;
  • .apply(lambda row: ..., axis=1) — вызывается для всего дата-фрейма целиком и поэтому внутрь row передается вся строка дата-фрейма, благодаря чему можно обращаться к нескольким столбцам сразу. Обратите внимание что в таком случае указываем axis=1)

  • Не забывайте про обработку крайних случаев (например, деление на ноль).
  • Используйте lambda только для простых операций — сложную логику лучше выносить в отдельную функцию.
  • Практикуйтесь на типичных задачах: расчёт метрик (CTR, конверсия, ROI), преобразование строк, создание новых признаков.

Методы соединения таблиц: merge, join, concat

Что могут спросить. Чем отличается merge от join, когда нужен concat, что будет по умолчанию у how и как не потерять строки при соединении, как проверить дубликаты перед merge.

В этом очень важно разбираться, поскольку часто у нас есть нескольких табличек из разных источников, которые нужно объединять между собой

Где чаще ошибаются. Иногда забывают, что merge по умолчанию делает inner join, а это значит, что часть строк может просто исчезнуть.

Мини-задача. В архиве MovieLens лежат два куска рейтингов (ratings1 и ratings2), таблица фильмов (movies) и отдельный файл с датами (dates). Нужно собрать единый набор данных и присоединить названия фильмов к получившемуся набору пользовательских рейтингов.
ratings = (
   pd.concat([ratings1, ratings2], ignore_index=True)
   .drop_duplicates(subset=["userId", "movieId", "rating"])
   .reset_index(drop=True)
   .assign(date=pd.to_datetime(dates["date"]))
   .merge(movies, on="movieId", how="left")
)
ratings
Разбор. Здесь использованы три полезных инструмента:

  • concat — склеивает ratings1 и ratings2, тем самым формируя единую таблицу пользовательских рейтингов;
  • drop_duplicates — убирает повторы после склейки (под повтором в данном случае мы будем понимать одну и ту же оценку от пользователя для одного фильма);
  • merge — присоединяет справочник фильмов по ключу movieId. Делаем соединение через left, поскольку хотим сохранить в результирующем наборе все строки из рейтингов, даже если соответствующего фильма нет в справочнике movies
Рекомендации по подготовке:

  • Потренируйтесь на небольших таблицах и вручную позапускайте скрипты с использованием concat, merge, join.
  • Чётко запомните типы соединений (inner, left, right, outer) и их поведение — это важный момент, на который часто обращают внимание.
  • Следите за дубликатами: проверяйте их до и после объединения, чтобы не получить искажённые данные.
  • Следите за соответствием ключей и их типов (movieId в данном случае).
  • Практикуйтесь комбинировать разные методы объединения данных (concat → очистка → merge) — именно такие цепочки чаще всего встречаются в реальной работе.

Сводные таблицы

Что могут спросить. Построить сводную таблицу по двум измерениям, выбрать агрегат, объяснить разницу между pivot и pivot_table.

Почему это важно. Сводная таблица - это быстрый способ получить аккуратную двухмерную таблицу без длинной простыни кода.

Где чаще ошибаются. Используют pivot, когда в данных есть дубликаты комбинаций индекс–колонка, и получают ошибку. В таких случаях нужен pivot_table, потому что он умеет избавляться от дубликатов

Мини-задача. По melb_data_fe.csv построить сводную таблицу медианной цены: строки — тип недвижимости, столбцы — месяц продажи.
(
   melb_fe
   .pivot_table(
       values="Price",
       index="Type",
       columns="MonthSale",
       aggfunc="median"
   )
   .round(0)
)
Разберём по шагам:
  • pivot_table(...) — строит сводную таблицу, где:
  • values="Price" — значения, которые мы агрегируем (цена недвижимости);
  • index="Type" — строки таблицы (тип недвижимости: дом, квартира и т.д.);
  • columns="MonthSale" — столбцы (месяц продажи);
  • aggfunc="median" — функция агрегации (берём медиану цены).

На выходе получаем для каждой пары (тип недвижимости × месяц продажи) медианную цену, в соответствии с условием задачи.

Как готовиться. Прогнать 5–6 примеров: сумма, среднее, медиана, одна и две размерности, сравнение pivot и pivot_table.

Базовый синтаксис Python

Типы данных

Что могут спросить. Разницу между основными типами данные list, tuple, set, dict, понятие изменяемых и неизменяемых объектов, а иногда — почему словарные ключи должны быть хешируемыми. Помимо этого полезно понимать, в каких случаях использовать каждый из типов данных.

Как выбрать подходящий тип данных на собеседовании:

- Если нужна последовательность, которую вы будете менять, выбирайте список.

- Если нужна уникальность - выбирайте множество.

- Понимаешь, что задача звучит как «ключ - значение» - берите словарь.

- Если нужны неизменные значения - выбирайте кортеж.

Где чаще ошибаются. Путают frozenset и tuple, забывают, что list, dict, set изменяемы, а str, tuple, int, float — нет.

Cоветуем прочитать серию статей на Хабре для повторения : Python: коллекции, часть 1/4: классификация, общие подходы и методы, конвертация / Хабр

Мини-вопрос. У вас есть список user_id, в котором возможны повторы. Нужно быстро убрать дубликаты и потом много раз проверять, встречался ли пользователь раньше. Что будете делать?

Решение ниже:
user_ids = [101, 102, 101, 103, 102]
seen = set(user_ids)
print(seen)          # {101, 102, 103}
print(102 in seen)   # True
Разбор. Здесь set — правильный выбор: он хранит только уникальные значения и хорошо подходит для проверок на вхождение. Если бы вам был важен исходный порядок и возможность добавлять элементы по позициям, нужен был бы список.

Как готовиться. Для каждого типа данных ответьте себе на один вопрос: в какой реальной аналитической задаче я бы его выбрал? Если вы можете объяснить это простым языком, с темой всё хорошо.

Циклы for и while

Что могут спросить. Как пройти по списку, как посчитать сумму или количество, как остановиться по условию, зачем нужны break и continue, чем for отличается от while, что делает enumerate, как работает range. В наших уроках по Python для собеседований это разобрано как основа, которая нужна для решения простых алгоритмических задач

Почему это важно именно аналитику. Потому что даже если в повседневной работе вы в основном живёте в pandas и SQL, на интервью вам легко могут дать маленькую задачу на чистом Python: пройти по списку, найти максимум, собрать словарь частот, обработать текст, остановиться при первом найденном условии и так далее.

Где чаще ошибаются. Забывают, что range(stop) не включает stop, в while забывают менять переменную цикла и получают бесконечный цикл, а ещё пишут for i in range(len(lst)), когда можно было обойтись обычным for value in lst или enumerate. В документации Python enumerate() прямо рекомендуется как более чистый способ получить индекс и значение одновременно.

Мини-задача. Просуммировать только положительные значения и при этом сохранить доступ к индексу.
values = [12, -3, 7, 0, 5]
total = 0
for i, value in enumerate(values):
if value <= 0:
       continue
   total += value
print(total)  # 24
Разбор. Здесь интервьюер обычно смотрит сразу на несколько вещей: умеете ли вы итерироваться по последовательности, понимаете ли условие continue, знаете ли enumerate, умеете ли пользоваться каунтерами.

Как готовиться. Порешать десяток коротких задач: сумма по условию, поиск первого элемента, частотный словарь, разворот списка, обработка строки, простой while с выходом по условию.

Функции

Здесь готовьтесь ответить на такие вопросы: Что такое параметр и аргумент, чем print в теле функции отличается от return, что происходит без явного return, как работает область видимости, как задаются аргументы по умолчанию, в чём подвох изменяемых значений по умолчанию

Это важно, поскольку аналитический код быстро превращается в кашу, если каждая логика живёт в одном длинном ноутбуке без функций. Функции — это способ делать код переиспользуемым, тестируемым и объяснимым.

Где чаще ошибаются. Пишут функцию, которая что-то печатает, но ничего не возвращает. Злоупотребляют глобальными переменными. Ставят список или словарь в значение по умолчанию. Путаются в позиционных и именованных аргументах. Пытаются засунуть в lambda половину ноутбука (не надо так).

Мини-вопрос. Что вернёт функция без return?
def mean_price(values):
    print(sum(values) / len(values))


prices = [100, 200, 300]
result = mean_price(prices)


print("Результат функции:", result)
Если такую функцию вызвать и сохранить результат в переменную, в переменной окажется None, потому что без return функция ничего не возвращает. Официальная дока Python это проговаривает прямо: return без выражения возвращает None.
Правильнее так:
def mean_price(values):
    return sum(values) / len(values)


prices = [100, 200, 300]
result = mean_price(prices)


print("Результат функции:", result)

Что ещё может встретиться в базовом Python

Есть две темы, которые не всегда стоят в обязательной программе, но всплывают достаточно стабильно, чтобы их не игнорировать:
  • list comprehensions. Позволяет лаконично создавать списки по шаблону:
[выражение for i in итератор if условие]. Например, [x**2 for x in range(10)]

  • try/except и raise на уровне чтения кода. Важно понимать, как перехватить ошибку и как явно сигнализировать о невалидности в коде

Как готовиться к задачам на базовый Python

Самая лучшая стратегия - решить 15–20 коротких задач руками. Если хотите воспользоваться нейронкой для решения, то лучше просить у них подсказки, но не полное решение. Также полезно смотреть на чужие решения, чтобы развивать насмотренность . Делать это можно на курсе Python для собеседований, обсуждая решение задач в комментариях.

Что повторить за несколько дней до собеседования

Если времени мало, приоритет такой:

  • Повторите базовый синтаксис. Чем отличаются == от is, как пользоваться in, разница между изменяемыми и неизменяемые типами, for / while, enumerate, break / continue, return, None, аргументы по умолчанию
  • После чего можно повторить основы pandas: фильтрация, groupby , agg , sort_values.
  • Затем отдельно пройдитесь по merge / join / concat
  • И в самом конце — 5–7 коротких практических задач на реальных табличках. Не читайте решения: лучше пишите код руками и проговаривайте его вслух.

Источники и что почитать дальше

Полезные материалы по интервью (на английском):

  • Dataquest: хороший разбор Python-вопросов именно для data-ролей
  • Interview Query: полезно почитать, чтобы уловить саму логику интервью на аналитика данных
  • StrataScratch: хорошие обзоры типов pandas-задач, которые реально похожи на интервьюшные задачи.