Яка різниця між об'єднанням та злиттям у Pandas?


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індексів 's. Пам'ятайте, індекси для приєднання. Хоча merge () є більш загальним методом.
Jiapeng Zhang

Відповіді:


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. left vs Internal join: 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 є функцією в просторі імен панд, і вона також доступна як метод екземпляра DataFrame, при цьому виклик DataFrame неявно вважається лівим об'єктом при з'єднанні.

Пов'язаний DataFrame.joinметод використовує mergeвнутрішньо для приєднання індекс-індекс та індекс-стовпець, але приєднується до індексів за замовчуванням, а не намагається приєднатись до загальних стовпців (поведінка за замовчуванням для 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
Це безумовно має бути прийнятою відповіддю! Дякую за ваше пояснення
Йохан Обадія

@ Матіас Фріп, Мабуть, для більш досвідчених це само собою зрозуміло, але можна також сказати, що "пошук у правій таблиці: df1.join (df2) може бути замінений на df1.join (df2, on = key_or_keys?
spacedustpi

@spacedustpi, я думаю, ви говорите, що ви можете використовувати on=key_or_keysдля зміни способу знаходження рядків у правій таблиці. Однак це насправді не так. onАргумент змінює пошук на ліву таблицю ( df1) від індексу до колонку (с). Однак навіть з цим аргументом правильна таблиця ( df2) буде узгоджена через її індекс. (Див. Останній приклад вище.)
Маттіас Фріпп,

У Pandas є кілька методів вирішення цих ситуацій, серед них злиття, приєднання, додавання, стиснення, поєднання, поєднання_перших. Погляньте на кожен із них, щоб побачити, який із них найкраще підходить для вашої ситуації
xiaxio

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 надає єдину функцію, об'єднуючись, як точка входу для всіх стандартних операцій об’єднання бази даних між об'єктами 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

Це правильно. Якщо ми об'єднаємо два кадри даних у стовпчиках, відмінних від індексів, ми отримаємо новий індекс, але якщо об'єднаємо індекси обох фреймів даних, то отримаємо кадр даних з тим самим індексом. Отже, щоб отримати той самий індекс після злиття, ми можемо зробити стовпці наш індекс (на якому ми хочемо об'єднатись) для обох кадрів даних, а потім об'єднати кадри даних із новоствореним індексом.
hasan najeeb

Дуже проникливий. Мені ніколи не була потрібна індексація (я зазвичай просто скидаю індекс), але це може призвести до значних змін у деяких випадках.
Ірен

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 - це зовнішнє / внутрішнє з'єднання, і Pandas join - це природне об'єднання". Отже, коли ви використовуєте об'єднання в пандах, ви хочете вказати, який тип sqlish приєднання ви хочете використовувати, тоді як, коли ви використовуєте приєднання до панд, ви дійсно хочете мати відповідну мітку стовпця, щоб забезпечити її приєднання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.