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


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

Это верно. Если мы объединим два фрейма данных в столбцы, отличные от индексов, мы получим новый индекс, но если мы объединим индексы обоих фреймов данных, мы получим фрейм данных с тем же индексом. Таким образом, чтобы получить тот же индекс после слияния, мы можем сделать столбцы нашим индексом (по которому мы хотим слить) для обоих фреймов данных, а затем слить фреймы данных по вновь созданному индексу.
Хасан Наджиб

Очень проницательно Я никогда не нуждался в индексации (обычно я просто сбрасывал индекс), но в некоторых случаях это может иметь большое значение.
Ирэн

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, вы действительно хотите иметь соответствующую метку столбца, чтобы обеспечить ее объединение.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.