В чем разница между объединением и слиянием в пандах?

208

Предположим, у меня есть два DataFrames, например, так:

left = pd.DataFrame({'key1': ['foo', 'bar'], 'lval': [1, 2]})

right = pd.DataFrame({'key2': ['foo', 'bar'], 'rval': [4, 5]})

Я хочу объединить их, поэтому я пытаюсь что-то вроде этого:

pd.merge(left, right, left_on='key1', right_on='key2')

И я счастлив

    key1    lval    key2    rval
0   foo     1       foo     4
1   bar     2       bar     5

Но я пытаюсь использовать метод соединения, который, как мне показалось, довольно похож.

left.join(right, on=['key1', 'key2'])

И я получаю это:

//anaconda/lib/python2.7/site-packages/pandas/tools/merge.pyc in _validate_specification(self)
    406             if self.right_index:
    407                 if not ((len(self.left_on) == self.right.index.nlevels)):
--> 408                     raise AssertionError()
    409                 self.right_on = [None] * n
    410         elif self.right_on is not None:

AssertionError: 

Чего мне не хватает?

бурундук
источник
4
Конкретная проблема здесь заключается в том, что mergeсоединяет столбцы leftс столбцами right, что вам нужно, но join(... on=[...])объединяет столбцы leftс индексными ключами right, а это не то, что вам нужно. Смотрите мой ответ ниже для более подробной информации.
Матиас Фрипп
3
DataFrame.join () всегда хочет сопоставить индексы или ключи вызывающей стороны (указанные onопцией) otherс индексами. Помните, индексы для объединения. В то время как merge () является более общим методом.
Цзяпэн Чжан

Ответы:

87

Я всегда использую joinпо индексам:

import pandas as pd
left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]}).set_index('key')
right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]}).set_index('key')
left.join(right, lsuffix='_l', rsuffix='_r')

     val_l  val_r
key            
foo      1      4
bar      2      5

Такую же функциональность можно получить, используя mergeследующие столбцы:

left = pd.DataFrame({'key': ['foo', 'bar'], 'val': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'val': [4, 5]})
left.merge(right, on=('key'), suffixes=('_l', '_r'))

   key  val_l  val_r
0  foo      1      4
1  bar      2      5
Пол Х
источник
Кажется, ошибка говорит о том, что он ожидает, что мультииндекс на rightтой же глубине, что и длина на on. Это имеет смысл для меня вроде. Я могу принять, что семантика различна. Но я хотел бы знать, смогу ли я вести себя так же с df.join
munk
346

pandas.merge() является базовой функцией, используемой для всех действий слияния / объединения.

DataFrames обеспечивают pandas.DataFrame.merge()и pandas.DataFrame.join()методы как удобный способ получить доступ к возможностям pandas.merge(). Например, df1.merge(right=df2, ...)эквивалентно pandas.merge(left=df1, right=df2, ...).

Это основные различия между df.join()и df.merge():

  1. поиск по правой таблице: df1.join(df2)всегда присоединяется через индекс df2, но df1.merge(df2)может присоединяться к одному или нескольким столбцам df2(по умолчанию) или к индексу df2right_index=True).
  2. поиск по левой таблице: по умолчанию df1.join(df2) используется индекс df1и df1.merge(df2)столбцы столбца df1. Это можно изменить, указав df1.join(df2, on=key_or_keys)или df1.merge(df2, left_index=True).
  3. оставлено против внутреннего соединения: df1.join(df2) выполняет левое соединение по умолчанию (сохраняет все строки df1), но df.mergeвыполняет внутреннее соединение по умолчанию (возвращает только совпадающие строки df1и df2).

Итак, общий подход заключается в использовании pandas.merge(df1, df2) или df1.merge(df2). Но для ряда распространенных ситуаций (сохранение всех строк df1и присоединение к индексу df2) вы можете сохранить некоторую типизацию, используя df1.join(df2)вместо этого.

Некоторые примечания по этим вопросам из документации по адресу http://pandas.pydata.org/pandas-docs/stable/merging.html#database-style-dataframe-joining-merging :

merge является функцией в пространстве имен pandas, и она также доступна как метод экземпляра DataFrame, при этом вызывающий DataFrame неявно считается левым объектом в соединении.

Связанный DataFrame.joinметод, используетmerge внутренне для соединений index-on-index и index-on-column (s), но объединяет индексы по умолчанию, а не пытается объединить общие столбцы (поведение по умолчанию для merge). Если вы присоединяетесь к индексу, вы можете использовать его DataFrame.joinдля экономии времени при наборе текста.

...

Эти два вызова функций полностью эквивалентны:

left.join(right, on=key_or_keys)
pd.merge(left, right, left_on=key_or_keys, right_index=True, how='left', sort=False)
Матиас Фрипп
источник
19
Это определенно должен быть принятый ответ! Спасибо за ваше объяснение
Йохан Обадия
@Matthias Fripp, Возможно, для более опытных это само собой разумеется, но можно также сказать, что «поиск по правой таблице: df1.join (df2) может быть переопределен к df1.join (df2, on = key_or_keys?
spacedustpi
@spacedustpi, я думаю, вы говорите, что вы можете использовать, on=key_or_keysчтобы изменить способ нахождения строк в правой таблице. Однако на самом деле это не так. onАргумент изменяет поиск на левую таблицу ( df1) от индекса к колонку (с). Однако даже с этим аргументом правильная таблица ( df2) будет сопоставлена ​​по индексу. (См. Последний пример выше.)
Матиас Фрипп
У Pandas есть несколько методов для работы с этими ситуациями, среди которых слияние, соединение, добавление, конкат, объединение, объединение_первых. Взгляните на каждый из них, чтобы
понять,
13

Я считаю, что join()это просто удобный метод. Попробуйте df1.merge(df2)вместо этого, что позволяет указать left_onи right_on:

In [30]: left.merge(right, left_on="key1", right_on="key2")
Out[30]: 
  key1  lval key2  rval
0  foo     1  foo     4
1  bar     2  bar     5
Ной
источник
11

Из этой документации

Pandas предоставляет единственную функцию merge в качестве точки входа для всех стандартных операций соединения базы данных между объектами DataFrame:

merge(left, right, how='inner', on=None, left_on=None, right_on=None,
      left_index=False, right_index=False, sort=True,
      suffixes=('_x', '_y'), copy=True, indicator=False)

И :

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

result = pd.merge(left, right, left_index=True, right_index=True,
how='outer')
Ромэн Жуан
источник
8

Одно из различий заключается в том, что mergeсоздается новый индекс и joinсохраняется индекс левой стороны. Это может иметь большое значение для ваших последующих преобразований, если вы ошибочно предполагаете, что ваш индекс не был изменен merge.

Например:

import pandas as pd

df1 = pd.DataFrame({'org_index': [101, 102, 103, 104],
                    'date': [201801, 201801, 201802, 201802],
                    'val': [1, 2, 3, 4]}, index=[101, 102, 103, 104])
df1

       date  org_index  val
101  201801        101    1
102  201801        102    2
103  201802        103    3
104  201802        104    4

-

df2 = pd.DataFrame({'date': [201801, 201802], 'dateval': ['A', 'B']}).set_index('date')
df2

       dateval
date          
201801       A
201802       B

-

df1.merge(df2, on='date')

     date  org_index  val dateval
0  201801        101    1       A
1  201801        102    2       A
2  201802        103    3       B
3  201802        104    4       B

-

df1.join(df2, on='date')
       date  org_index  val dateval
101  201801        101    1       A
102  201801        102    2       A
103  201802        103    3       B
104  201802        104    4       B
SteCo
источник
Это верно. Если мы объединим два фрейма данных в столбцы, отличные от индексов, мы получим новый индекс, но если мы объединим индексы обоих фреймов данных, мы получим фрейм данных с тем же индексом. Таким образом, чтобы получить тот же индекс после слияния, мы можем сделать столбцы нашим индексом (по которому мы хотим слить) для обоих фреймов данных, а затем слить фреймы данных по вновь созданному индексу.
Хасан Наджиб
Очень проницательно Я никогда не нуждался в индексации (обычно я просто сбрасывал индекс), но в некоторых случаях это может иметь большое значение.
Ирэн
4
  • Присоединение: индекс по умолчанию (Если любое имя столбца совпадает, в режиме по умолчанию будет выдано сообщение об ошибке, поскольку вы не определили lsuffix или rsuffix)
df_1.join(df_2)
  • Объединение: имена столбцов по умолчанию (если имя столбца не совпадает, в режиме по умолчанию будет выдано сообщение об ошибке)
df_1.merge(df_2)
  • on параметр имеет разное значение в обоих случаях
df_1.merge(df_2, on='column_1')

df_1.join(df_2, on='column_1') // It will throw error
df_1.join(df_2.set_index('column_1'), on='column_1')
жесткий
источник
2

Чтобы выразить это аналогично SQL "слияние панд означает внешнее / внутреннее соединение, а соединение панд - естественное соединение". Следовательно, когда вы используете слияние в pandas, вы хотите указать, какой тип sqlish объединения вы хотите использовать, тогда как когда вы используете pandas join, вы действительно хотите иметь соответствующую метку столбца, чтобы обеспечить ее объединение.

Kaustubh J
источник