Как объединить DataFrame в pandas
Карьерник — квиз-тренажёр в Telegram с 1500+ вопросами для собесов аналитика. SQL, Python, A/B, метрики. Бесплатно.
Три способа объединения
pd.merge()— по ключу (аналог SQL JOIN)pd.concat()— по оси (вертикально или горизонтально)df.join()— по индексу (упрощённый merge)
1. merge — самый частый
import pandas as pd
users = pd.DataFrame({
'user_id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Carol']
})
orders = pd.DataFrame({
'order_id': [101, 102, 103],
'user_id': [1, 1, 2],
'total': [100, 200, 50]
})
# INNER JOIN
result = pd.merge(users, orders, on='user_id')
# LEFT JOIN
result = pd.merge(users, orders, on='user_id', how='left')
# OUTER JOIN
result = pd.merge(users, orders, on='user_id', how='outer')Типы how
'inner'— только совпадения (default)'left'— все из левого, совпавшие из правого'right'— все из правого'outer'— все из обоих'cross'— декартово произведение (pandas 1.2+)
2. merge по разным колонкам
pd.merge(
left=users,
right=orders,
left_on='id', # колонка в users
right_on='user_id' # колонка в orders
)3. merge по нескольким ключам
pd.merge(df1, df2, on=['country', 'city'])4. Переименование колонок при merge
Если есть конфликтующие колонки:
pd.merge(df1, df2, on='user_id', suffixes=('_a', '_b'))
# name_a и name_b вместо name_x и name_y (default)5. concat — сложить под или сбоку
# вертикально (одна под другой)
pd.concat([df1, df2])
# горизонтально
pd.concat([df1, df2], axis=1)
# сбросить индекс
pd.concat([df1, df2]).reset_index(drop=True)concat аналогичен SQL UNION ALL.
6. concat с разными колонками
Если в df1 колонок нет в df2:
pd.concat([df1, df2])
# недостающие заполняются NaN
# только общие колонки
pd.concat([df1, df2], join='inner')7. join — по индексу
# merge смотрит на колонки, join — на индекс
result = df1.join(df2) # по индексу
result = df1.join(df2, how='left')Удобно, когда индекс — это ключ (например, user_id как индекс).
8. merge vs concat vs join
| Задача | Функция |
|---|---|
| JOIN двух таблиц по ключу | pd.merge |
| UNION ALL (стакать под) | pd.concat(axis=0) |
| Сбоку приклеить по индексу | pd.concat(axis=1) или df.join |
| JOIN по индексу | df.join |
9. Проверка качества merge
# indicator=True добавляет колонку _merge
result = pd.merge(df1, df2, on='id', how='outer', indicator=True)
# смотрим, где совпали
result['_merge'].value_counts()
# both 100
# left_only 5
# right_only 3Используйте, чтобы проверить, корректно ли работает merge.
10. Many-to-many — осторожно
Если в обоих DataFrame ключ неуникален, merge даст cartesian (каждая со каждой в группе ключа).
# users: 1 строка на юзера
# orders: N строк на юзера
merge ok: users × orders → N строк
# users: 5 строк на юзера (почему-то)
# orders: 3 строки на юзера
# merge: 15 строк на юзера — вероятно, ошибкаПроверяйте через validate:
pd.merge(df1, df2, on='user_id', validate='one_to_many')
# one_to_one, one_to_many, many_to_one, many_to_many11. Объединить много DataFrame
from functools import reduce
dfs = [df1, df2, df3, df4]
result = reduce(lambda a, b: pd.merge(a, b, on='user_id'), dfs)Частые ошибки
1. Дубликаты после merge
Часто из-за неуникальных ключей. Проверьте через df.duplicated('key').sum().
2. Потерянные строки
INNER JOIN + один ключ отсутствует в одной таблице → строка пропадает. Используйте LEFT.
3. Забыть suffixes
# pandas сам добавит _x и _y
pd.merge(df1, df2, on='user_id')
# df1.name → name_x
# df2.name → name_yПонятнее — явные suffixes.
4. concat с разным индексом
df1 = pd.DataFrame(..., index=[0, 1, 2])
df2 = pd.DataFrame(..., index=[0, 1, 2])
pd.concat([df1, df2])
# индекс: [0, 1, 2, 0, 1, 2] — дубли
# нужно reset_index(drop=True)Связанные темы
FAQ
merge vs join?
merge — по колонкам. join — по индексу. merge универсальнее.
concat или merge?
concat — стакать (UNION). merge — JOIN по ключу.
Как сохранить порядок?
merge нарушает порядок. Для сохранения — добавить sort-колонку и сортировать после.
Cartesian случился, что делать?
Проверить уникальность ключа в обеих таблицах. Добавить validate='one_to_many'.
Тренируйте pandas — откройте тренажёр с 1500+ вопросами для собесов.