# метод `DataFrame`, который считается # левым объектом в соединении new_df = DataFrame.merge(right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=None, indicator=False, validate=None) # функция пространства имен pandas # аргумент `left` - это левый `DataFrame` import pandas as pd new_df = pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=None, indicator=False, validate=None)
right
- DataFrame
или именованный Series
для слияния. Именованный Series
- это значит имеет не пустой атрибут Series.name
.
how='inner'
- тип слияния, которое необходимо выполнить.
Принимает следующие строки:
left
: использовать ключи только из левого DataFrame
, аналогично левому внешнему соединению SQL. Сохраняет порядок ключей.right
: использовать ключи только из правого DataFrame
, аналогично правому внешнему соединению SQL. Сохраняет порядок ключей.outer
: использовать объединение ключей из обоих DataFrame
, аналогично полному внешнему соединению SQL. Сортирует ключи лексикографически.inner
: использовать пересечение ключей из обоих DataFrame
, аналогично внутреннему соединению SQL. Сохраняет порядок левых ключей.cross
: создает декартово произведение из обоих DataFrame
, сохраняет порядок левых ключей.on=None
- список имен индексов или уровней столбцов для объединения. Они должны присутствовать в обоих DataFrames
. Если включено значение None
и индексы не объединяются, то по умолчанию это пересечение столбцов в обоих DataFrames
.
left_on=None
- имена индексов или уровней столбцов для объединения в левом DataFrame
. Также может быть массивом или списком массивов длиной с левый DataFrame
. Эти массивы обрабатываются так, как если бы они были столбцами.
right_on=None
- имена индексов или уровней столбцов для объединения в правом DataFrame
. Также может быть массивом или списком массивов длиной с правый DataFrame
. Эти массивы обрабатываются так, как если бы они были столбцами.
left_index=False
- использовать индекс из левого DataFrame
в качестве ключа(ей) соединения. Если это MultiIndex
, то количество ключей в другом DataFrame
(либо индекс, либо количество столбцов) должно соответствовать количеству уровней.
right_index=False
- использовать индекс из правого DataFrame
в качестве ключа(ей) соединения. Если это MultiIndex
, то количество ключей в другом DataFrame
(либо индекс, либо количество столбцов) должно соответствовать количеству уровней.
sort=False
- лексикографическая сортировка ключей соединения в результирующем DataFrame
. Если значение равно False
, порядок ключей соединения зависит от типа соединения (аргумент how
).
suffixes=('_x', '_y')
- суффикс, добавляемый к перекрывающимся именным столбцам слева и справа соответственно. Значение None
вместо строки указывает, что имя столбца слева или справа следует оставить как есть, без суффикса.
copy=None
- если значение равно False
, по возможности избегает копирования.
Аргумент
copy
изменит поведение в pandas 3.0. Копирование при записи будет включено по умолчанию, а это означает, что все методы с аргументомcopy
будут использовать механизм отложенного копирования и игнорировать аргументcopy
. Ключевой аргументcopy
будет удален в будущей версииpandas
. Можно уже сейчас получить будущее поведение и улучшения, включив копирование при записиpd.options.mode.copy_on_write = True
indicator=False
- если значение True
, то в выходной DataFrame
добавляется столбец с именем _merge
с информацией об источнике каждой строки. Столбцу можно дать другое имя, указав строку вместо True
.
Столбец будет иметь категориальный тип со значением:
left_only
для наблюдений, ключ которых появляется только в левом DataFrame
, right_only
для наблюдений, ключ которых появляется только в правом DataFrame
, both
, если ключ слияния наблюдения находится в обоих DataFrame
.validate=None
- если указано, то проверяет, имеет ли соединение указанный тип.
Принимает следующие строки:
'one_to_one'
или '1:1'
: проверяет, уникальны ли ключи соединения как в левом, так и в правом наборах данных.'one_to_many'
или '1:m'
: проверяет, уникальны ли ключи соединения в левом наборе данных.'many_to_one'
или 'm:1'
: проверяет, уникальны ли ключи соединения в правом наборе данных.'many_to_many'
или 'm:m'
: допускается, но не приводит к проверкам.DataFrame
двух объединенных объектов.DataFrame.merge()
Метод DataFrame.merge()
модуля pandas
выполняет объединение DataFrame
или именованные объекты Series
(считаются левым объектом) с помощью соединения в стиле базы данных.
Именованный объект Series
рассматривается как DataFrame
с одним именованным столбцом.
Соединение выполняется по столбцам или индексам. При соединении, в которых участвуют столбцы - индексы DataFrame
будут проигнорированы. В противном случае, при соединении индексов с индексами или индексов в столбце или столбцах, индекс будет передан дальше. При выполнении перекрестного слияния не допускаются никакие спецификации столбцов для слияния.
Функция pandas.merge()
это функция в пространстве имен библиотеки pandas
, она также доступна как метод экземпляра DataFrame merge()
(представленный выше), при этом вызывающий DataFrame
неявно считается левым объектом в соединении.
Предупреждение. Если оба ключевых столбца содержат строки, где ключ имеет значение
NA
, то эти строки будут сопоставлены друг с другом. Это отличается от обычного поведения соединения SQL и может привести к неожиданным результатам.
Опытные пользователи реляционных баз данных, таких как SQL, знакомы с терминологией, используемой для описания операций соединения между двумя структурами, подобными таблицам SQL (объектами DataFrame
).
Есть несколько случаев, которые очень важно понять:
one-to-one
: например, при соединении двух объектов DataFrame
по их индексам (которые должны содержать уникальные значения).many-to-one
: например, при присоединении индекса (уникального) к одному или нескольким столбцам в другом DataFrame
.many-to-many
: соединение столбцов со столбцами.Примечание. При объединении столбцов со столбцами (возможно, соединение
many-to-many
) любые индексы переданных объектовDataFrame
будут отброшены.
В SQL (стандартной реляционной алгебре), если комбинация ключей встречается более одного раза в обеих таблицах, то результирующая таблица будет иметь декартово произведение связанных данных. Для понимания о чем речь, простой пример с одной уникальной комбинацией ключей:
>>> import pandas as pd left = pd.DataFrame( { "key": ["K0", "K1", "K2", "K3"], "A": ["A0", "A1", "A2", "A3"], "B": ["B0", "B1", "B2", "B3"], } ) right = pd.DataFrame( { "key": ["K0", "K1", "K2", "K3"], "C": ["C0", "C1", "C2", "C3"], "D": ["D0", "D1", "D2", "D3"], } ) >>> pd.merge(left, right, on="key") # key A B C D # 0 K0 A0 B0 C0 D0 # 1 K1 A1 B1 C1 D1 # 2 K2 A2 B2 C2 D2 # 3 K3 A3 B3 C3 D3
Более сложный пример с несколькими ключами соединения. Присутствуют только ключи, появляющиеся слева и справа (пересечение), т.к. соединение по умолчанию how='inner'
.
left = pd.DataFrame( { "key1": ["K0", "K0", "K1", "K2"], "key2": ["K0", "K1", "K0", "K1"], "A": ["A0", "A1", "A2", "A3"], "B": ["B0", "B1", "B2", "B3"], } ) right = pd.DataFrame( { "key1": ["K0", "K1", "K1", "K2"], "key2": ["K0", "K0", "K0", "K0"], "C": ["C0", "C1", "C2", "C3"], "D": ["D0", "D1", "D2", "D3"], } ) >>> pd.merge(left, right, on=["key1", "key2"]) # key1 key2 A B C D # 0 K0 K0 A0 B0 C0 D0 # 1 K1 K0 A2 B2 C1 D1 # 2 K1 K0 A2 B2 C2 D2
how
Аргумент how
определяет, какие ключи должны быть включены в результирующую таблицу. Если комбинация ключей не встречается ни в левой, ни в правой таблице, то значения в объединенной таблице будут иметь значение NA
. Ниже приведена краткая информация о параметрах how
и их эквивалентных именах в SQL:
Метод объединения | Аналог SQL | Описание |
left | LEFT OUTER JOIN | Использует ключи только из левого DataFrame |
right | RIGHT OUTER JOIN | Использует ключи только из правого DataFrame |
outer | FULL OUTER JOIN | Использует объединение ключей из обоих DataFrame |
inner | INNER JOIN | Использует пересечение ключей из обоих DataFrame |
cross | CROSS JOIN | Создает декартово произведение строк обоих DataFrame. |
# how="left" >>> pd.merge(left, right, how="left", on=["key1", "key2"]) # key1 key2 A B C D # 0 K0 K0 A0 B0 C0 D0 # 1 K0 K1 A1 B1 NaN NaN # 2 K1 K0 A2 B2 C1 D1 # 3 K1 K0 A2 B2 C2 D2 # 4 K2 K1 A3 B3 NaN NaN # how="right" >>> pd.merge(left, right, how="right", on=["key1", "key2"]) # key1 key2 A B C D # 0 K0 K0 A0 B0 C0 D0 # 1 K1 K0 A2 B2 C1 D1 # 2 K1 K0 A2 B2 C2 D2 # 3 K2 K0 NaN NaN C3 D3 # how="outer" >>> pd.merge(left, right, how="outer", on=["key1", "key2"]) # key1 key2 A B C D # 0 K0 K0 A0 B0 C0 D0 # 1 K0 K1 A1 B1 NaN NaN # 2 K1 K0 A2 B2 C1 D1 # 3 K1 K0 A2 B2 C2 D2 # 4 K2 K1 A3 B3 NaN NaN # 5 K2 K0 NaN NaN C3 D3 # how="inner" >>> pd.merge(left, right, how="inner", on=["key1", "key2"]) # key1 key2 A B C D # 0 K0 K0 A0 B0 C0 D0 # 1 K1 K0 A2 B2 C1 D1 # 2 K1 K0 A2 B2 C2 D2 # how="cross" >>> pd.merge(left, right, how="cross") # key1_x key2_x A B key1_y key2_y C D # 0 K0 K0 A0 B0 K0 K0 C0 D0 # 1 K0 K0 A0 B0 K1 K0 C1 D1 # 2 K0 K0 A0 B0 K1 K0 C2 D2 # 3 K0 K0 A0 B0 K2 K0 C3 D3 # 4 K0 K1 A1 B1 K0 K0 C0 D0 # 5 K0 K1 A1 B1 K1 K0 C1 D1 # 6 K0 K1 A1 B1 K1 K0 C2 D2 # 7 K0 K1 A1 B1 K2 K0 C3 D3 # 8 K1 K0 A2 B2 K0 K0 C0 D0 # 9 K1 K0 A2 B2 K1 K0 C1 D1 # 10 K1 K0 A2 B2 K1 K0 C2 D2 # 11 K1 K0 A2 B2 K2 K0 C3 D3 # 12 K2 K1 A3 B3 K0 K0 C0 D0 # 13 K2 K1 A3 B3 K1 K0 C1 D1 # 14 K2 K1 A3 B3 K1 K0 C2 D2 # 15 K2 K1 A3 B3 K2 K0 C3 D3
Пример с повторяющимися ключами соединения в DataFrames
:
>>> left = pd.DataFrame({"A": [1, 2], "B": [2, 2]}) >>> right = pd.DataFrame({"A": [4, 5, 6], "B": [2, 2, 2]}) >>> pd.merge(left, right, on="B", how="outer") # A_x B A_y # 0 1 2 4 # 1 1 2 5 # 2 1 2 6 # 3 2 2 4 # 4 2 2 5 # 5 2 2 6
Предупреждение. Объединение/слияние повторяющихся ключей может привести к возвращению
DataFrames
, который является умножением измерений строки, что может привести к переполнению памяти
validate
)Можно использовать аргумент validate
, для автоматической проверки, нет ли дубликатов в ключах слияния. Уникальность ключа проверяется перед операциями слияния и поэтому должна защищать от переполнения памяти. Проверка уникальности ключа также является хорошим способом убедиться в том, что структуры данных соответствуют ожиданиям.
В следующем примере, правый DataFrame
содержит повторяющиеся значения в столбце B
. Так как это не слияние один к одному, как указано в аргументе validate
, будет вызвано исключение. Так как это не слияние 'one_to_one'
, как указано в аргументе validate
, будет возбуждено исключение.
>>> pd.merge(left, right, on="B", how="outer", validate="one_to_one") # Traceback (most recent call last): # ... # pandas.errors.MergeError: Merge keys are not unique in right dataset; not a one-to-one merge
Если пользователь знает о дубликатах в правом DataFrame
, но хочет убедиться, что в левом DataFrame
нет дубликатов, то можно использовать аргумент validate='one_to_many'
, который не вызовет исключения.
>>> pd.merge(left, right, on="B", how="outer", validate="one_to_many") # A_x B A_y # 0 1 1 NaN # 1 2 2 4.0 # 2 2 2 5.0 # 3 2 2 6.0
indicator
)Метод DataFrame.merge()
принимает аргумента indicator
. Если задано значение True
, то к выходному объекту будет добавлен столбец категориального типа с именем _merge
, который принимает значения:
left_only
- объединен ключ только в левом DataFrame
, right_only
- объединен ключ только в правом DataFrame
, both
- объединены ключи в обоих DataFrame
.>>> df1 = pd.DataFrame({"col1": [0, 1], "col_left": ["a", "b"]}) >>> df2 = pd.DataFrame({"col1": [1, 2, 2], "col_right": [2, 2, 2]}) >>> pd.merge(df1, df2, on="col1", how="outer", indicator=True) # col1 col_left col_right _merge # 0 0 a NaN left_only # 1 1 b 2.0 both # 2 2 NaN 2.0 right_only # 3 2 NaN 2.0 right_only
Аргумент indicator
также принимает строку, и в этом случае переданная строка будет использоваться в качестве имени столбца вместо _merge
.
>>> pd.merge(df1, df2, on="col1", how="outer", indicator="indicator_column") # col1 col_left col_right indicator_column # 0 0 a NaN left_only # 1 1 b 2.0 both # 2 2 NaN 2.0 right_only # 3 2 NaN 2.0 right_only
DataFrame.merge()
:Больше примеров смотрите в материале "Сравнение
pandas
с SQL"...
Создадим два DataFrame
, с которыми будем работать:
import pandas as pd df1 = pd.DataFrame({'lkey': ['foo', 'bar', 'baz', 'foo'], 'value': [1, 2, 3, 5]}) df2 = pd.DataFrame({'rkey': ['foo', 'bar', 'baz', 'foo'], 'value': [5, 6, 7, 8]}) >>> df1 # lkey value # 0 foo 1 # 1 bar 2 # 2 baz 3 # 3 foo 5 # df2 # rkey value # 0 foo 5 # 1 bar 6 # 2 baz 7 # 3 foo 8
Слияние df1
и df2
в столбцах lkey
и rkey
. К столбцам значений добавляются суффиксы по умолчанию, _x
и _y
>>> df1.merge(df2, left_on='lkey', right_on='rkey') # lkey value_x rkey value_y # 0 foo 1 foo 5 # 1 foo 1 foo 8 # 2 foo 5 foo 5 # 3 foo 5 foo 8 # 4 bar 2 bar 6 # 5 baz 3 baz 7
Слияние df1
и df2
с указанными левым и правым суффиксами, добавленными ко всем перекрывающимся столбцам.
>>> df1.merge(df2, left_on='lkey', right_on='rkey', suffixes=('_left', '_right')) # lkey value_left rkey value_right # 0 foo 1 foo 5 # 1 foo 1 foo 8 # 2 foo 5 foo 5 # 3 foo 5 foo 8 # 4 bar 2 bar 6 # 5 baz 3 baz 7
Попробуем объединить df1
и df2
без указания суффиксов suffixes=(False, False)
, при этом поднимается исключение, если DataFrame
имеют перекрывающиеся столбцы.
>>> df1.merge(df2, left_on='lkey', right_on='rkey', suffixes=(False, False)) # Traceback (most recent call last): # ... # ValueError: columns overlap but no suffix specified: # Index(['value'], dtype='object')
Для демонстрации объединения без указания суффиксов создадим новые DataFrame
:
>>> df1 = pd.DataFrame({'a': ['foo', 'bar'], 'b': [1, 2]}) >>> df2 = pd.DataFrame({'a': ['foo', 'baz'], 'c': [3, 4]}) >>> df1 # a b # 0 foo 1 # 1 bar 2 >>> df2 # a c # 0 foo 3 # 1 baz 4
Соединение DataFrame
как SQL INNER JOIN
по ключу - столбец 'a'
:
>>> df1.merge(df2, how='inner', on='a') # a b c # 0 foo 1 3
Соединение DataFrame
как SQL LEFT OUTER JOIN
по ключу - столбец 'a'
:
>>> df1.merge(df2, how='left', on='a') # a b c # 0 foo 1 3.0 # 1 bar 2 NaN
Перекрестное соединение. Для большей наглядности создадим новые DataFrame
:
>>> df1 = pd.DataFrame({'left': ['foo', 'bar']}) >>> df2 = pd.DataFrame({'right': [7, 8]}) >>> df1 # left # 0 foo # 1 bar >>> df2 # right # 0 7 # 1 8
>>> df1.merge(df2, how='cross') # left right # 0 foo 7 # 1 foo 8 # 2 bar 7 # 3 bar 8