Вопросы по pandas и numpy на собеседовании
Pandas спрашивают у аналитиков и дата-сайентистов как рабочий инструмент: как соединить таблицы, не потеряв строк, почему датафрейм занял всю память и что быстрее цикла.
Из чего состоит тема
Так тема разложена в тренажёре: движок ведёт прогресс по каждой подтеме отдельно и возвращает те, где вы ошибаетесь.
- pandas: датафреймы40
- numpy: векторизация16
- Временные ряды в pandas10
- Reshape и merge в pandas9
Разборы подтем
Конспект по каждой: что это, как отвечать вслух, на чём валятся, плюс вопросы для самопроверки.
- Векторизация в NumPy16 вопросов
- Pandas и NumPy: основы40 вопросов
- Reshape и merge в pandas9 вопросов
- Временные ряды в pandas10 вопросов
Примеры вопросов с разбором
- Что делает broadcasting в numpy?A)Рассылает копию массива по сети на все воркеры распределённого кластера для параллельных вычислений над нимB)Согласует формы массивов разного размера в операции, виртуально растягивая меньший без копированияC)Принудительно приводит все элементы массива к единому строковому типу перед выполнением операцииD)Транслирует события изменения массива подписчикам по паттерну publisher-subscriber в реальном времени по сети
показать ответ и разбор
+B)Согласует формы массивов разного размера в операции, виртуально растягивая меньший без копирования// разбор: Broadcasting — правила, по которым numpy применяет операцию к массивам разной формы без явных циклов и копий: меньший массив логически «растягивается» вдоль недостающих осей (например, вектор прибавляется к каждой строке матрицы). Реального дублирования данных не происходит — это виртуальное расширение, отсюда и скорость, и экономия памяти. К сети и строкам отношения не имеет.
- pandas падает по памяти на датасете больше RAM. Что разумно сделать?A)Просто очень много раз подряд перезапускать ровно тот же скрипт до успешного проходаB)Перевести все числовые колонки в строковый тип ради экономии памятиC)Загрузить датасет целиком ещё раз, но уже сразу в двух копияхD)Читать чанками, взять Polars/Dask или вынести обработку в Spark
показать ответ и разбор
+D)Читать чанками, взять Polars/Dask или вынести обработку в Spark// разбор: pandas держит датафрейм целиком в памяти. Варианты: читать файл чанками (chunksize) и агрегировать по частям; ужать типы (downcast чисел, категориальные колонки для строк); перейти на ленивый Polars/Dask; при действительно больших данных — вынести обработку в распределённый Spark. Перезапуски и превращение чисел в строки только усугубляют проблему.
- Категориальную колонку кодируешь через pd.get_dummies. Какая ловушка ждёт при применении к новым данным?A)Get_dummies не умеет работать со строковыми категориями, поэтому их сначала кодируют вручнуюB)На инференсе категории могут не совпасть — reindex по колонкам обучения (fill_value=0) или энкодерC)Get_dummies даёт ровно две колонкиD)One-hot кодирование в pandas недоступно
показать ответ и разбор
+B)На инференсе категории могут не совпасть — reindex по колонкам обучения (fill_value=0) или энкодер// разбор: get_dummies строит колонки по категориям, встреченным в ЭТОМ наборе. На новых данных категории могут не совпасть с обучением: новые дадут лишние колонки, отсутствующие — пропадут, и матрица признаков перестанет соответствовать модели. Решение: зафиксировать колонки обучения и привести к ним новые данные (reindex(columns=train_cols, fill_value=0)) или использовать обучаемый OneHotEncoder (sklearn) с handle_unknown.
- В колонке строки-даты, нужны фичи «день недели» и «месяц». Как это делают в pandas векторно?A)pd.to_datetime(col), затем .dt.dayofweek и .dt.monthB)Питоновским циклом с datetime.strptime по каждой строкеC)Применить.apply(lambda x: x.weekday()) прямо к строковой колонке без приведения к datetimeD)Строки-даты в признаки превращают только ручным парсингом посимвольно
показать ответ и разбор
+A)pd.to_datetime(col), затем .dt.dayofweek и .dt.month// разбор: Сначала колонку приводят к datetime: pd.to_datetime(col) (можно задать format для скорости и надёжности). Затем аксессор .dt даёт векторный доступ к компонентам: .dt.dayofweek (0=пн), .dt.month, .dt.hour, .dt.is_month_end и т.д. Это быстрее и чище питоновского цикла или .apply, потому что операции идут по всей колонке разом на уровне C.
- Чем df.apply(func, axis=1) хуже векторизации и когда всё же оправдан?A)Ничем не хуже: apply по строкам работает с той же скоростью, что и векторная операцияB)Apply возвращает результат в неверном перемешанном порядке строк, поэтому его не стоит применятьC)Apply по строкам умеет работать с числовыми колонками и падает на строковых данныхD)apply(axis=1) — питон-цикл по строкам под капотом, медленно; оправдан для логики, не сводимой к векторам
показать ответ и разбор
+D)apply(axis=1) — питон-цикл по строкам под капотом, медленно; оправдан для логики, не сводимой к векторам// разбор: apply(axis=1) вызывает питон-функцию на каждую строку — это тот же медленный цикл, просто спрятанный, и на больших данных он в разы уступает векторным операциям и np.where/np.select. Брать его стоит, когда логику честно нельзя выразить векторно (сложное ветвление, вызов внешней функции) и объёмы невелики. По скорости он не равен вектору и порядок строк не путает.
- Почему векторизованная операция numpy/pandas обычно быстрее цикла for по элементам?A)Операция уходит в скомпилированный C-код без питон-оверхеда на каждой итерации циклаB)Векторизация незаметно распараллеливает цикл сразу на все ядра процессора вообще без какой-либо настройкиC)Numpy автоматически кэширует результат каждой операции и при повторном вызове просто отдаёт готовое из кэшаD)Цикл for в python не способен обрабатывать элементы массива numpy без ошибки несовместимости типа
показать ответ и разбор
+A)Операция уходит в скомпилированный C-код без питон-оверхеда на каждой итерации цикла// разбор: В numpy/pandas векторная операция выполняется единым проходом в скомпилированном C поверх непрерывного блока памяти — питон не платит за интерпретацию, боксинг объектов и накладные расходы цикла на каждый элемент. Питоновский for гоняет интерпретатор на каждой итерации, отсюда разница в разы-десятки раз. Это не про многоядерность и не про кэш.
- Есть длинная таблица (user, month, value). Нужна широкая: строки — user, столбцы — month. Чем сделать?A)Склеить все месяцы через concat по оси столбцов, выровняв их по общему индексу пользователейB)Melt по всем колонкамC)pivot_table(index,columns,values,aggfunc) или set_index([...]).unstack(); при дублях нужен агрегатD)Drop_duplicates по user
показать ответ и разбор
+C)pivot_table(index,columns,values,aggfunc) или set_index([...]).unstack(); при дублях нужен агрегат// разбор: Перевод long→wide делают pivot_table (index=строки, columns=разворачиваемое поле, values=значения, aggfunc для схлопывания дублей) либо set_index([...]).unstack(), который поднимает уровень MultiIndex в колонки. Если пара (user, month) встречается не единожды, «чистый» pivot упадёт на дублях — нужен pivot_table с агрегатом. Обратная операция (wide→long) — melt/stack.
- Дневные события надо свести к недельным/месячным агрегатам по индексу-дате. Какой инструмент pandas?A)Groupby по строковой дате как естьB)Просуммировать все строки без учёта времениC)Развернуть данные через pivot_table по годам и месяцам вручную, а потом сложить нужные периодыD)df.resample('W').sum() на DatetimeIndex — режет ось времени на периоды
показать ответ и разбор
+D)df.resample('W').sum() на DatetimeIndex — режет ось времени на периоды// разбор: resample — это groupby по времени: на DatetimeIndex он бьёт ось на равные периоды (правило 'D','W','M','Q','ME' и т.п.) и применяет агрегат (sum, mean, agg с несколькими функциями). Он корректно обрабатывает пропущенные периоды и границы, в отличие от ручного groupby по строке даты. Для скользящих (не разбивающих ось) окон берут rolling, а не resample.
- Перемножаете два больших int64-массива, результат вдруг отрицательный, а ошибки нет. Что случилось?A)numpy молча переполнил фиксированный int64: результат не влез в 64 бита и обернулся по модулюB)Numpy на переполнении сам повышает тип до Python-bigint, значит отрицательный результат — это определённо баг numpyC)Такого встречается редко: на переполнении целых numpy кидает OverflowError и падаетD)Это ошибки округления float — надо было заранее привести массивы к float64
показать ответ и разбор
+A)numpy молча переполнил фиксированный int64: результат не влез в 64 бита и обернулся по модулю// разбор: numpy-целые фиксированной ширины (int64), и арифметика над ними по умолчанию оборачивается по модулю 2**64 без предупреждения — в отличие от Python-int неограниченной точности. Произведение больших чисел не влезает в 64 бита и «переворачивается» в мусорное (часто отрицательное) значение. Ошибки нет, потому что это штатная модульная арифметика. Защита: следить за масштабом, считать в float64/object или в питоновском int.
это 9 из 75
Ещё 66 вопросов по теме — в тренажёре, с движком повторения
Прочитать разбор и ответить самому — разные навыки. В Сеньорчике вопросы идут сессиями, а движок возвращает подтемы, где вы ошибаетесь, пока они не начнут отскакивать. Бесплатно, лимит по энергии.
Частые вопросы
Что спрашивают про merge в pandas?
Типы соединений и что происходит с дублями ключей, разницу между merge и join по индексу, как проверять размер результата и не терять строки молча.
Как ускорить обработку датафрейма?
Векторизованные операции вместо циклов и apply, правильные типы данных включая категориальные, чтение только нужных колонок и переход к чанкам или другому инструменту на больших объёмах.