Как объединять DataFrame в Pandas: руководство и примеры
Если вы используете Python, даже для простых задач, вы, вероятно, знакомы с важностью сторонних библиотек. Pandas — библиотека с мощной поддержкой DataFrame — одна из таких. DataFrame — это двумерная таблица с метками строк и столбцов. DataFrame удобно использовать для хранения и анализа структурированных данных.
Вы можете импортировать разные типы файлов в DataFrame и создавать версии, чтобы хранить различные наборы данных. После импорта данных в DataFrame вы можете объединять их для подробного анализа.
Коротко о подходе и терминах
- DataFrame — таблица с индексами и столбцами. Используется для анализа табличных данных.
- Merge — операция объединения двух DataFrame по ключевым столбцам или индексам, аналог JOIN в SQL.
- Concat — прицепление (конкатенация) DataFrame друг к другу по строкам или столбцам.
Важно: выбирайте метод исходя из структуры данных и желаемого результата. Ниже — пошаговые примеры и рекомендации.
Основы: создаём DataFrame для примеров
Перед тем как объединять, нужно иметь DataFrame. Для разработки удобно создавать тестовые словари и преобразовывать их в DataFrame.
Создаём DataFrame в Python
Сначала импортируйте Pandas:
import pandas as pdСоздайте словари и преобразуйте их в DataFrame. В примере ниже используются два словаря с общим полем user_id — это «ключ», по которому позже будем объединять таблицы.
dict1 = {"user_id": ["001", "002", "003", "004", "005"],
"FName": ["John", "Brad", "Ron", "Roald", "Chris"],
"LName": ["Harley", "Cohen", "Dahl", "Harrington", "Kerr-Hislop"]}
dict2 = {"user_id": ["001", "002", "003", "004"], "Age": [15, 28, 34, 24]}
# Преобразуем в DataFrame
df1 = pd.DataFrame(dict1)
df2 = pd.DataFrame(dict2)Некоторые IDE позволяют визуально просмотреть DataFrame, но код выполняется одинаково в любом окружении.
Объединение с помощью pd.merge
Функция merge — гибкий инструмент для объединения двух DataFrame по ключам. Общий синтаксис:
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
left_index=False, right_index=False, suffixes=('_x', '_y'),
indicator=False, validate=None)Коротко о параметрах (одна строчка на термин):
- left, right — объединяемые DataFrame.
- how — тип объединения: ‘left’, ‘right’, ‘inner’, ‘outer’.
- on — имя столбца(ов) общего ключа, существующих в обоих DataFrame.
- left_on / right_on — разные имена ключей в левой и правой таблице.
- left_index / right_index — использовать индекс вместо столбца.
- suffixes — суффиксы для конфликтующих имён столбцов.
- indicator — добавляет столбец с информацией, откуда пришла строка.
- validate — проверка типа объединения (например, ‘one_to_one’).
Примеры типичных сценариев:
1) Простое объединение по общему столбцу (on)
merged = pd.merge(df1, df2, how='left', on='user_id')
print(merged)- left-merge сохранит все строки из df1 и подтянет совпадения из df2.
- inner-merge вернёт только строки, у которых есть совпадение в обоих таблицах.
- right-merge аналогично left, но сохраняет все строки из df2.
- outer-merge вернёт все строки из обеих таблиц, заполняя отсутствующие значения NaN.
2) Объединение по разным именам ключей
# Допустим, в правой таблице ключ называется id
# merged = pd.merge(left_df, right_df, left_on='user_id', right_on='id')3) Объединение по индексам
# Если индекс содержит уникальные ключи
# merged = pd.merge(df1.set_index('user_id'), df2.set_index('user_id'),
# left_index=True, right_index=True, how='inner')4) Разрешение конфликтов имён столбцов и индикатор изменений
merged = pd.merge(df1, df2, on='user_id', how='outer',
suffixes=('_left', '_right'), indicator=True)
print(merged['_merge'].value_counts())indicator даёт столбец _merge со значениями ‘left_only’, ‘right_only’ и ‘both’ — полезно для диагностики потерь данных.
5) Валидация формы объединения
Параметр validate позволяет проверить допущения, например, one_to_one, one_to_many и т.д. Если ожидания не совпадут, будет выброшено исключение.
# Пример: ожидаем отношение один-к-одному
# pd.merge(df1, df2, on='user_id', validate='one_to_one')Когда merge лучше всего подходит
- Нужно объединить таблицы по ключу(ам).
- Требуется линия поведения для несопадающих строк (left/right/outer).
- Нужна диагностика происхождения строк (indicator).
Типичные виды объединений (на примере)
Inner — пересечение по ключам
inner = pd.merge(df1, df2, how='inner', on='user_id')Left — сохранить все строки левого DataFrame
left = pd.merge(df1, df2, how='left', on='user_id')Right — сохранить все строки правого DataFrame
right = pd.merge(df1, df2, how='right', on='user_id')Outer — объединить всё
outer = pd.merge(df1, df2, how='outer', on='user_id')pd.concat: конкатенация DataFrame
Функция concat удобна, когда нужно «склеить» таблицы по строкам или по столбцам. Общий синтаксис:
pd.concat(objs, axis=0, join='outer', ignore_index=False, keys=None)Ключевые примечания:
- axis=0 (по умолчанию) — вертикальная конкатенация, т.е. добавление строк (стекование вниз).
- axis=1 — горизонтальная конкатенация, т.е. добавление столбцов (объединение по индексам).
- join=’outer’ сохраняет все индексы/столбцы; join=’inner’ оставляет пересечение.
- ignore_index=True сбрасывает индекс в результирующей таблице.
- keys создаёт иерархический индекс (MultiIndex), указывающий источник каждой части.
Примеры:
# Вертикальное объединение (стандартное): добавляем строки
vertical = pd.concat([df1, df2], axis=0, ignore_index=True, sort=False)
# Горизонтальное объединение: соединяем по индексу
horizontal = pd.concat([df1.set_index('user_id'), df2.set_index('user_id')],
axis=1, join='outer')
# Только пересечение по индексам
joined_inner = pd.concat([df1.set_index('user_id'), df2.set_index('user_id')],
axis=1, join='inner')Как выбирать между merge, concat и join
- Используйте merge, когда нужно объединение по ключу(ам) и контроль типа join, суффиксов и индикатора.
- Используйте concat, когда нужно просто склеить таблицы по одному из измерений (добавить строки или столбцы).
- DataFrame.join — удобный метод для быстрого объединения по индексам, эквивалент pd.concat(axis=1) или pd.merge(…, left_index=True, right_index=True).
Частые ошибки и когда объединение даёт неправильный результат
- Отсутствие уникального ключа: если ключи не уникальны, вы получите декартово произведение для соответствующих групп.
- Различные типы данных в ключах (строка vs число): перед merge приведение типов обязательно.
- Пропущенные значения в ключах приведут к Unexpected NaN в результатах.
- Ошибочное понимание axis в concat: axis=0 — вертикально (добавляем строки), axis=1 — горизонтально (добавляем столбцы).
Важно: всегда проверяйте shape и доли уникальных ключей до и после объединения.
Практическая методика (мини-SOP)
- Проверить ключи: уникальность, типы, пропуски.
- Привести типы ключей к общему виду (str/int/datetime).
- Выбрать метод: merge (ключи) или concat/join (индексы/добавление строк).
- Выполнить объединение с indicator=True для первой проверки.
- Проанализировать counts: как много left_only/right_only/both.
- Применить suffixes при пересечении имён столбцов.
- Валидировать результат: shape, дубликаты, контрольные суммы по группам.
Чеклист по ролям
Data Engineer:
- Привёл типы ключей и убрал пропуски.
- Оценил размер и память перед объединением.
- Использовал validate при больших операциях.
Data Scientist:
- Убедился, что объединение не дублирует образцы.
- Проверил распределения ключевых признаков до/после объединения.
Аналитик:
- Протестировал ключи на семпле.
- Использовал indicator и посчитал несопадения.
Разработчик приложения:
- Обработал NaN и согласовал схемы данных.
- Настроил логирование операций объединения.
Критерии приёмки
- Все ожидаемые строки присутствуют в результирующем DataFrame по правилам выбранного типа объединения.
- Форматы типов колонок соответствуют спецификации.
- Нет неожиданных дубликатов или пропусков в ключевых столбцах.
- Результат покрыт автоматизированными тестами для ключевых сценариев.
Примеры тест-кейсов и приёмочных сценариев
- Тест 1: inner-merge двух таблиц с уникальными ключами => количество строк = количество общих ключей.
- Тест 2: left-merge => все строки левой таблицы присутствуют; правые столбцы заполнены или NaN.
- Тест 3: concat axis=0 с ignore_index=True => индекс должен быть последовательным от 0.
- Тест 4: merge с validate=’one_to_one’ на данных с дубликатами => должно выбросить ошибку.
Пара практических приёмов и оптимизаций
- При больших объёмах: устанавливайте индексы и используйте merge по индексам, это часто быстрее.
- Если ключи не уникальны по дизайну, подумайте, действительно ли нужен merge, или нужен агрегат перед объединением.
- Используйте chunking (чтение и объединение частями) для экономии памяти при работе с большими файлами.
- Для логирования добавляйте столбец-источник с помощью keys или indicator, чтобы отслеживать, откуда пришли строки.
Модель принятия решения (Mermaid)
flowchart TD
A[Есть ли общий ключ?] -->|Да| B{Ключ уникален?}
A -->|Нет| C[Используйте concat или join по индексам]
B -->|Да| D[Использовать merge 'on/left_on/right_on']
B -->|Нет| E[Агрегируйте/дедуплицируйте, затем merge]
D --> F{Нужно сохранить все строки одной таблицы?}
F -->|Левая| G[how='left']
F -->|Правая| H[how='right']
F -->|Нет| I[how='inner' или 'outer']Краткая галерея крайних случаев
- Большое несоответствие ключей (много left_only) — возможно, проблема в предпроцессинге.
- Дубликаты ключей в обеих таблицах — результат будет множиться; рассмотрите агрегирование.
- Смешение типов: ‘001’ vs 1 — приведите оба к str или int.
1‑строчный глоссарий
- DataFrame — двумерная таблица данных в Pandas.
- Merge — объединение по ключам.
- Concat — склеивание таблиц по оси.
- Index — метка строк, используемая для выравнивания при concat/join.
Резюме
Pandas предоставляет мощные и гибкие инструменты для объединения таблиц: pd.merge для объединения по ключам и pd.concat для конкатенации по осям. Перед объединением проверьте ключи, приведение типов и ожидаемую форму результата. Используйте indicator и validate для отладки и автоматических проверок. Применяйте чеклист из статьи, чтобы снизить риск ошибок при объединении.
Важно: всегда тестируйте объединение на небольших примерах и проверяйте распределения после слияния.
Примечание: приведённые примеры обучающие; адаптируйте параметры под вашу схему данных и объёмы.