0Pricing
Pandas & NumPy Academy · Урок

pd.merge: внутреннее и внешнее объединение

Объединяйте два DataFrame по общему ключевому столбцу с помощью внутренних и внешних объединений и определяйте, какие строки сохраняются или удаляются.

«pd.merge: внутреннее и внешнее объединение» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.

Что такое объединение

Объединение комбинирует два DataFrame, сопоставляя строки по общему ключевому столбцу — это та же концепция, что и предложение JOIN в SQL. Pandas реализует объединения через pd.merge(). В отличие от pd.concat(), который просто складывает данные, pd.merge() интеллектуально сопоставляет строки двух разных таблиц на основе совпадающих значений в одном или нескольких столбцах.

Общий ключевой столбец

Для объединения в обоих DataFrames должен быть хотя бы один столбец с общими значениями — ключевой столбец. Например, таблица orders содержит столбец customer_id, и в таблице customers также есть столбец customer_id. Объединение по customer_id добавляет сведения о клиенте к каждой строке заказа. Если оба DataFrame используют одинаковое имя столбца, укажите ключ с помощью параметра on.

import pandas as pd

orders = pd.DataFrame({
    'order_id': [1, 2, 3, 4],
    'customer_id': [101, 102, 101, 103],
    'amount': [250, 80, 320, 150]
})

customers = pd.DataFrame({
    'customer_id': [101, 102, 104],
    'name': ['Alice', 'Bob', 'Diana']
})

Внутреннее объединение: пересечение обеих таблиц

Внутреннее объединение (используется по умолчанию) сохраняет только строки, в которых значение ключа существует в обоих DataFrames. Строки любой таблицы, для которых в другой таблице нет соответствующего ключа, молча удаляются. В примере с заказами у клиентов 103 и 104 нет соответствий в другой таблице, поэтому их строки исключаются из результата внутреннего объединения.

# Inner join (default): only matching rows from both
result = pd.merge(orders, customers, on='customer_id', how='inner')
print(result)
#    order_id  customer_id  amount   name
# 0         1          101     250  Alice
# 1         3          101     320  Alice
# 2         2          102      80    Bob
# Order 4 (customer 103) dropped - no match in customers
# Diana (customer 104) dropped - no match in orders

Внешнее объединение: объединение обеих таблиц

Внешнее объединение (how='outer') сохраняет все строки из обоих DataFrames. Если для строки нет соответствующего ключа в другой таблице, отсутствующие столбцы заполняются значением NaN. Это полезно, когда требуется полная картина по обоим наборам данных с сохранением записей, для которых не нашлось соответствия.

result = pd.merge(orders, customers, on='customer_id', how='outer')
print(result)
#    order_id  customer_id  amount   name
# 0       1.0          101   250.0  Alice
# 1       3.0          101   320.0  Alice
# 2       2.0          102    80.0    Bob
# 3       4.0          103   150.0    NaN  <- order with unknown customer
# 4       NaN          104     NaN  Diana  <- customer with no orders

Объединение по столбцам с разными именами

Если ключевой столбец имеет разные имена в каждом DataFrame, используйте left_on и right_on вместо on. Pandas сопоставляет строки, в которых значение left_on в левом DataFrame равно значению right_on в правом DataFrame. Оба ключевых столбца попадут в результат; один из дублирующих столбцов можно удалить позже.

products = pd.DataFrame({
    'prod_id': [10, 20, 30],
    'name': ['Widget', 'Gadget', 'Doohickey']
})

order_lines = pd.DataFrame({
    'item_id': [10, 10, 20],
    'qty': [3, 1, 5]
})

result = pd.merge(order_lines, products,
                  left_on='item_id', right_on='prod_id')
print(result.drop(columns='prod_id'))
#    item_id  qty    name
# 0       10    3  Widget
# 1       10    1  Widget
# 2       20    5  Gadget

Объединение по нескольким столбцам

Чтобы сопоставлять строки по комбинации столбцов (составному ключу), передайте список параметру on. Это распространено, когда одного столбца недостаточно для однозначного сопоставления, например при объединении одновременно по year и region. Для включения строки в результат значения всех указанных столбцов должны совпадать.

targets = pd.DataFrame({
    'year': [2023, 2023, 2024],
    'region': ['East', 'West', 'East'],
    'target': [100, 150, 120]
})
actuals = pd.DataFrame({
    'year': [2023, 2024, 2024],
    'region': ['East', 'East', 'West'],
    'actual': [95, 115, 80]
})

result = pd.merge(targets, actuals, on=['year', 'region'], how='inner')
print(result)
#    year region  target  actual
# 0  2023   East     100      95
# 1  2024   East     120     115

Обработка совпадающих имён столбцов

Если в обоих DataFrame есть столбец с одинаковым именем (кроме ключевого), Pandas добавляет суффиксы, чтобы их различать. По умолчанию это _x (слева) и _y (справа). Вы можете настроить их с помощью параметра suffixes, чтобы получить более понятные имена и избежать путаницы в результате.

df_a = pd.DataFrame({'id': [1, 2], 'value': [10, 20]})
df_b = pd.DataFrame({'id': [1, 2], 'value': [100, 200]})

# Default suffixes
print(pd.merge(df_a, df_b, on='id'))
#    id  value_x  value_y

# Custom suffixes
print(pd.merge(df_a, df_b, on='id', suffixes=('_budget', '_actual')))
#    id  value_budget  value_actual

Проверка неожиданных дубликатов

Распространённая проблема при слиянии — неожиданное умножение строк. Если в ключевом столбце обоих DataFrames есть повторяющиеся значения, слияние создаёт декартово произведение всех совпадающих строк. Всегда проверяйте количество строк после слияния: если оно больше ожидаемого, исследуйте дубликаты в ключевом столбце с помощью df.duplicated(subset=['key']).sum().

# Both tables have duplicate keys -> cartesian product
left = pd.DataFrame({'id': [1, 1], 'val_l': ['a', 'b']})
right = pd.DataFrame({'id': [1, 1], 'val_r': ['x', 'y']})

result = pd.merge(left, right, on='id')
print(len(result))  # 4 rows! (2x2 cartesian product)
print(result)
#    id val_l val_r
# 0   1     a     x
# 1   1     a     y
# 2   1     b     x
# 3   1     b     y

Параметр validate для безопасности

Передайте параметр validate, чтобы задать ограничения на связи при слиянии и вызвать ошибку, если они нарушены. 'one_to_one' требует уникальных ключей в обеих таблицах, 'one_to_many' — уникальных ключей только в левой таблице, а 'many_to_one' — только в правой. Это отличный приём защитного программирования, который помогает рано обнаруживать проблемы с качеством данных.

# Safe merge: validate that customer_id is unique in customers
try:
    result = pd.merge(orders, customers,
                      on='customer_id',
                      how='inner',
                      validate='many_to_one')
    print('Merge OK, shape:', result.shape)
except Exception as e:
    print('Merge error:', e)

Проверка охвата с помощью indicator

Передайте indicator=True, чтобы добавить в результат столбец _merge, показывающий источник каждой строки: 'left_only', 'right_only' или 'both'. Это особенно полезно после внешнего объединения, чтобы определить, для каких записей найдено совпадение, а для каких нет, и проверить качество данных перед удалением столбца-индикатора.

result = pd.merge(orders, customers, on='customer_id',
                  how='outer', indicator=True)
print(result['_merge'].value_counts())
# both           3
# left_only      1  <- orders with no customer record
# right_only     1  <- customers with no orders

# Find unmatched orders
print(result[result['_merge'] == 'left_only'])

Краткое сравнение внутреннего и внешнего объединений

Кратко сравним два типа объединения: внутреннее объединение даёт пересечение — только строки с совпадающими ключами в обоих DataFrames. Внешнее объединение даёт объединение — все строки из обоих DataFrames, с NaN там, где совпадения нет. Для полноты: левое объединение сохраняет все строки из левого DataFrame, а правое объединение — все строки из правого DataFrame. Эти темы рассматриваются в следующем уроке.

# Quick reference
# how='inner'  -> intersection: only matched rows
# how='outer'  -> union: all rows from both, NaN for no match
# how='left'   -> all left rows + matched right rows
# how='right'  -> all right rows + matched left rows

# Most common: inner (default) for enrichment, left for preserving records

Быстрая проверка

Проверьте, насколько хорошо Вы поняли внутреннее и внешнее объединения с помощью pd.merge из этого урока.

Итоги урока

В этом уроке Вы узнали, что pd.merge() с параметром how='inner' сохраняет только совпадающие строки из обоих DataFrames, а how='outer' сохраняет все строки, используя NaN для несовпадающих строк; on задаёт общий ключ, а left_on/right_on позволяют работать с разными именами столбцов; параметр indicator помогает проверить, какие строки совпали. Далее Вы изучите левые и правые объединения, сохраняющие все строки с одной стороны.

Часто задаваемые вопросы

Урок «pd.merge: внутреннее и внешнее объединение» бесплатный?

Да — полный текст урока «pd.merge: внутреннее и внешнее объединение» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.

Чему я научусь в уроке «pd.merge: внутреннее и внешнее объединение»?

Объединяйте два DataFrame по общему ключевому столбцу с помощью внутренних и внешних объединений и определяйте, какие строки сохраняются или удаляются. Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?

Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «pd.merge: внутреннее и внешнее объединение»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?

Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. pd.concat для объединения DataFrames
  2. pd.merge: внутреннее и внешнее объединение
  3. Левое и правое объединение
  4. Объединение по индексу
← Назад к Pandas & NumPy Academy