merge в Pandas — полный гайд по объединению таблиц
Коротко
pd.merge() — аналог SQL JOIN в Python. Берёт два DataFrame и соединяет их по общему ключу. Если вы знаете JOIN в SQL, разобраться с merge — дело пяти минут. На собеседованиях аналитика merge спрашивают в live-coding секции: дают два датафрейма и просят объединить, посчитать метрику, найти пропуски.
Базовый синтаксис
import pandas as pd
users = pd.DataFrame({
'user_id': [1, 2, 3, 4],
'name': ['Анна', 'Борис', 'Вика', 'Глеб']
})
orders = pd.DataFrame({
'user_id': [1, 1, 3, 5],
'amount': [500, 300, 1200, 800]
})
result = pd.merge(users, orders, on='user_id')По умолчанию merge делает inner join — оставляет только строки, где ключ есть в обеих таблицах. В примере выше Борис и Глеб (нет заказов) и user_id=5 (нет в users) выпадут.
Параметр how — тип соединения
Параметр how определяет, какие строки попадут в результат. Логика та же, что и в SQL JOIN:
| how | Аналог в SQL | Что делает |
|---|---|---|
'inner' |
INNER JOIN | Только совпадения (по умолчанию) |
'left' |
LEFT JOIN | Все строки из левого DataFrame |
'right' |
RIGHT JOIN | Все строки из правого DataFrame |
'outer' |
FULL OUTER JOIN | Все строки из обоих DataFrame |
# Все пользователи + их заказы (у кого нет — NaN)
result = pd.merge(users, orders, on='user_id', how='left')
# Все комбинации — никто не теряется
result = pd.merge(users, orders, on='user_id', how='outer')Самая частая ошибка на собесе: забыть указать how='left' и потерять строки без совпадений. По умолчанию merge делает inner — молча отбрасывает несопоставленные записи.
on, left_on, right_on — ключи соединения
Если столбец-ключ называется одинаково в обоих DataFrame — используйте on:
pd.merge(users, orders, on='user_id')Если названия различаются — left_on и right_on:
events = pd.DataFrame({
'uid': [1, 2, 3],
'event': ['login', 'purchase', 'login']
})
pd.merge(users, events, left_on='user_id', right_on='uid')Соединение по нескольким ключам — передайте список:
pd.merge(df1, df2, on=['user_id', 'date'])suffixes — конфликты имён столбцов
Если в обоих DataFrame есть столбец с одинаковым названием (не ключ), merge автоматически добавит суффиксы _x и _y. Можно задать свои:
users_with_city = pd.DataFrame({
'user_id': [1, 2], 'name': ['Анна', 'Борис'], 'source': ['organic', 'paid']
})
orders_with_source = pd.DataFrame({
'user_id': [1, 2], 'amount': [500, 300], 'source': ['web', 'app']
})
result = pd.merge(users_with_city, orders_with_source,
on='user_id',
suffixes=('_user', '_order'))
# Столбцы: user_id, name, source_user, amount, source_orderindicator — откуда строка
Параметр indicator=True добавляет столбец _merge, который показывает, из какого DataFrame пришла строка:
result = pd.merge(users, orders, on='user_id', how='outer', indicator=True)
print(result['_merge'].value_counts())
# both — совпадение в обоих
# left_only — только в левом (users)
# right_only — только в правом (orders)Удобно для дебага: быстро понять, кто не смерджился и почему.
Дубликаты и many-to-many
Если ключ не уникален в обоих DataFrame, merge делает декартово произведение по совпавшим ключам. Это главный источник «неожиданно разросшегося» DataFrame:
df1 = pd.DataFrame({'key': ['a', 'a'], 'val1': [1, 2]})
df2 = pd.DataFrame({'key': ['a', 'a'], 'val2': [10, 20]})
result = pd.merge(df1, df2, on='key')
# 4 строки вместо 2! Каждая строка df1 соединяется с каждой строкой df2Защита: перед merge проверяйте уникальность ключа через df['key'].duplicated().sum(). Или используйте параметр validate:
pd.merge(df1, df2, on='key', validate='one_to_many')
# Бросит MergeError, если ключ не уникален в левом DataFrameВарианты validate: 'one_to_one', 'one_to_many', 'many_to_one', 'many_to_many'.
merge vs join vs concat
| merge | join | concat | |
|---|---|---|---|
| Что делает | Соединение по столбцам (аналог SQL JOIN) | Соединение по индексу | Склейка по строкам или столбцам |
| Когда использовать | Объединение по ключу (user_id, date) | Оба DataFrame уже проиндексированы по ключу | Объединение однотипных таблиц (январь + февраль) |
| Синтаксис | pd.merge(df1, df2, on='key') |
df1.join(df2, on='key') |
pd.concat([df1, df2]) |
В 90% случаев на собеседовании нужен именно merge. concat полезен, когда нужно склеить одинаковые по структуре таблицы (например, данные за разные месяцы). join — редко используется, merge покрывает те же задачи.
Практический пример: воронка пользователей
Частая задача на собесе: есть пользователи и события, нужно посчитать конверсию.
users = pd.DataFrame({
'user_id': [1, 2, 3, 4, 5],
'reg_date': pd.to_datetime(['2025-01-01', '2025-01-02', '2025-01-03',
'2025-01-04', '2025-01-05']),
'source': ['organic', 'paid', 'organic', 'paid', 'organic']
})
purchases = pd.DataFrame({
'user_id': [1, 3],
'purchase_date': pd.to_datetime(['2025-01-05', '2025-01-10']),
'revenue': [990, 1490]
})
# LEFT merge — сохраняем всех пользователей
funnel = pd.merge(users, purchases, on='user_id', how='left')
# Конверсия в покупку
conversion = funnel['revenue'].notna().mean()
print(f'Конверсия: {conversion:.0%}') # 40%
# Конверсия по источнику
funnel.groupby('source')['revenue'].apply(lambda x: x.notna().mean())Частые ошибки
- Забыли
how='left'— потеряли строки без совпадений, даже не заметили. - Дубликаты в ключе — DataFrame размножился в 10 раз, метрики сломались.
- Разные типы ключа — в одном DataFrame ключ int, в другом str. Merge вернёт пустой результат без ошибки. Проверяйте
df['key'].dtype. - Несколько merge подряд без проверки — каждый merge может множить строки. Проверяйте
shapeпосле каждого.
Вопросы с собеседований
Чем merge отличается от join в pandas?
merge соединяет по столбцам (как SQL JOIN), join — по индексу. merge гибче: можно указать произвольные столбцы через on, left_on, right_on. На практике merge используют чаще.
Что произойдёт, если ключ не уникален в обоих DataFrame?
merge сделает декартово произведение по совпавшим ключам. Если в левом 3 строки с key='a' и в правом 2 строки с key='a', результат — 6 строк. Это many-to-many join. Чтобы защититься, используйте validate='one_to_many'.
Как проверить, какие строки не смерджились?
Использовать indicator=True. Merge добавит столбец _merge со значениями both, left_only, right_only. Строки left_only — те, что не нашли пару в правом DataFrame.
Какой how по умолчанию в merge?
inner — только совпадения. Это отличается от SQL, где тип JOIN указывается явно. Частая ошибка — забыть параметр how и молча потерять строки.
В чём разница merge и concat? merge соединяет по ключу «горизонтально» (добавляет столбцы). concat склеивает «вертикально» (добавляет строки). merge — это JOIN, concat — это UNION ALL.
Потренируйтесь решать задачи — откройте тренажёр с 1500+ вопросами для подготовки к собеседованиям аналитиков.
FAQ
Можно ли мерджить больше двух таблиц?
Да, но последовательно. Каждый вызов merge принимает два DataFrame. Для трёх таблиц — два merge подряд. Используйте functools.reduce, если таблиц много: reduce(lambda l, r: pd.merge(l, r, on='key'), [df1, df2, df3]).
Что быстрее — merge в pandas или JOIN в SQL? SQL. Базы данных оптимизированы для соединений: индексы, hash join, merge join. Pandas работает в оперативной памяти без индексов (если не создали явно). На больших данных (миллионы строк) разница ощутима.
Как сделать cross join в pandas?
pd.merge(df1, df2, how='cross') — доступно с pandas 1.2+. Возвращает декартово произведение всех строк.
Потренироваться в merge и других операциях pandas можно в Python-тренажёре. Там задачи в формате собеседования — с DataFrame, groupby и объединением таблиц. Больше примеров вопросов — на странице примеры вопросов, шпаргалка по всем операциям — в pandas шпаргалке.