INNER | (LEFT | RIGHT | FULL) OUTER) JOIN с пандами?merge? join? concat? update? ВОЗ? Какие? Почему?!... и больше. Я видел эти повторяющиеся вопросы о различных аспектах функциональности слияния панд. Большая часть информации о слиянии и различных вариантах его использования сегодня фрагментирована между десятками плохо сформулированных, не поддающихся поиску сообщений. Цель здесь - сопоставить некоторые из наиболее важных моментов для потомков.
Эти вопросы и ответы должны стать следующей частью серии полезных руководств пользователя по распространенным идиомам pandas (см. этот пост о повороте и этот пост о конкатенации, которых я коснусь позже).
Обратите внимание, что это сообщение нет, предназначенное для замены документация, так что прочтите и его! Некоторые примеры взяты оттуда.
For ease of access.






Дополнительный визуальный вид pd.concat([df0, df1], kwargs).
Обратите внимание, что значение kwarg axis=0 или axis=1 не так интуитивно понятно, как df.mean() или df.apply(func).
Встроенный документ Google "insert ==> drawing ... ==> new" (по состоянию на май 2019 г.). Но для ясности: единственная причина, по которой я использовал документ Google для этого изображения, заключается в том, что мои заметки хранятся в документе Google, и мне хотелось бы, чтобы изображение можно было быстро изменить в самом документе Google. На самом деле, теперь вы упомянули об этом, инструмент для рисования в Google doc довольно изящный.
Вау, это здорово. Исходя из мира SQL, «вертикальное» соединение - это не соединение в моей голове, поскольку структура таблицы всегда фиксирована. Теперь даже подумайте, что пандам следует объединить concat и merge с параметром направления horizontal или vertical.
@Ufos Разве это не axis=1 и axis=0?
да, теперь есть merge и concat, оси и все такое. Однако, как показывает @eliu, это все та же концепция слить с «левым», «правым» и «горизонтальным» или «вертикальным». Мне лично приходится заглядывать в документацию каждый раз, когда мне нужно вспомнить, какая «ось» - это 0, а какая - 1.
если возможно, кто-то должен обратиться к axis=0 и axis=1 в .mean() .apply() .dropna() .concat(). Мне нужно много думать, чтобы принимать решения по каждому случаю.
В этом ответе я рассмотрю практические примеры.
Второй - слияние фреймов данных из индекса одного и столбца другого.
Учитывая следующий DataFrames с такими же именами столбцов:
Preco2018 с размером (8784, 5)
Preco 2019 с размером (8760, 5)
У них такие же имена столбцов.
Вы можете комбинировать их, используя pandas.concat, просто
import pandas as pd
frames = [Preco2018, Preco2019]
df_merged = pd.concat(frames)
В результате получается DataFrame следующего размера (17544, 5)
Если вы хотите визуализировать, он работает так
(Источник)
2. Слияние по столбцу и индексу
В этой части я рассмотрю конкретный случай: если нужно объединить индекс одного фрейма данных и столбец другого фрейма данных.
Допустим, у вас есть фрейм данных Geo с 54 столбцами, один из которых является Date Data, который имеет тип datetime64[ns].
И фрейм данных Price, в котором есть один столбец с ценой и индексом, соответствует датам
В этом конкретном случае для их объединения используется pd.merge
merged = pd.merge(Price, Geo, left_index=True, right_on='Data')
В результате получается следующий фрейм данных
В этом посте будут рассмотрены следующие темы:
merge здесь недостатки)Часто возникает ситуация, когда необходимо объединить несколько DataFrames. Наивно, это можно сделать, объединив вызовы merge:
df1.merge(df2, ...).merge(df3, ...)
Однако для многих DataFrames это быстро выходит из-под контроля. Кроме того, может потребоваться обобщение для неизвестного количества DataFrames.
Здесь я представляю pd.concat для многосторонних соединений по ключам уникальный и DataFrame.join для многосторонних соединений по ключам неуникальный. Во-первых, настройка.
# Setup.
np.random.seed(0)
A = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'valueA': np.random.randn(4)})
B = pd.DataFrame({'key': ['B', 'D', 'E', 'F'], 'valueB': np.random.randn(4)})
C = pd.DataFrame({'key': ['D', 'E', 'J', 'C'], 'valueC': np.ones(4)})
dfs = [A, B, C]
# Note, the "key" column values are unique, so the index is unique.
A2 = A.set_index('key')
B2 = B.set_index('key')
C2 = C.set_index('key')
dfs2 = [A2, B2, C2]
Если ваши ключи (здесь ключ может быть либо столбцом, либо индексом) уникальны, вы можете использовать pd.concat. Обратите внимание, что pd.concat присоединяется к DataFrames в индексе.
# merge on `key` column, you'll need to set the index before concatenating
pd.concat([
df.set_index('key') for df in dfs], axis=1, join='inner'
).reset_index()
key valueA valueB valueC
0 D 2.240893 -0.977278 1.0
# merge on `key` index
pd.concat(dfs2, axis=1, sort=False, join='inner')
valueA valueB valueC
key
D 2.240893 -0.977278 1.0
Опустите join='inner' для ПОЛНОГО ВНЕШНЕГО СОЕДИНЕНИЯ. Обратите внимание, что вы не можете указать соединения LEFT или RIGHT OUTER (если они вам нужны, используйте join, описанный ниже).
concat работает быстро, но имеет свои недостатки. Он не может обрабатывать дубликаты.
A3 = pd.DataFrame({'key': ['A', 'B', 'C', 'D', 'D'], 'valueA': np.random.randn(5)})
pd.concat([df.set_index('key') for df in [A3, B, C]], axis=1, join='inner')
ValueError: Shape of passed values is (3, 4), indices imply (3, 2)
В этой ситуации мы можем использовать join, поскольку он может обрабатывать неуникальные ключи (обратите внимание, что join присоединяется к DataFrames по их индексу; он вызывает merge под капотом и выполняет LEFT OUTER JOIN, если не указано иное).
# join on `key` column, set as the index first
# For inner join. For left join, omit the "how" argument.
A.set_index('key').join(
[df.set_index('key') for df in (B, C)], how='inner').reset_index()
key valueA valueB valueC
0 D 2.240893 -0.977278 1.0
# join on `key` index
A3.set_index('key').join([B2, C2], how='inner')
valueA valueB valueC
key
D 1.454274 -0.977278 1.0
D 0.761038 -0.977278 1.0
Перейдите к другим темам в Pandas Merging 101, чтобы продолжить обучение:
* you are here
В этом посте будут рассмотрены следующие темы:
merge, join, concatThere are a few options, some simpler than others depending on the use case.
DataFrame.mergewithleft_indexandright_index(orleft_onandright_onusing names indexes)
- supports inner/left/right/full
- can only join two at a time
- supports column-column, index-column, index-index joins
DataFrame.join(join on index)
- supports inner/left (default)/right/full
- can join multiple DataFrames at a time
- supports index-index joins
pd.concat(joins on index)
- supports inner/full (default)
- can join multiple DataFrames at a time
- supports index-index joins
Настройка и основы
import pandas as pd
import numpy as np
np.random.seed([3, 14])
left = pd.DataFrame(data = {'value': np.random.randn(4)},
index=['A', 'B', 'C', 'D'])
right = pd.DataFrame(data = {'value': np.random.randn(4)},
index=['B', 'D', 'E', 'F'])
left.index.name = right.index.name = 'idxkey'
left
value
idxkey
A -0.602923
B -0.402655
C 0.302329
D -0.524349
right
value
idxkey
B 0.543843
D 0.013135
E -0.326498
F 1.385076
Обычно внутреннее соединение по индексу выглядит так:
left.merge(right, left_index=True, right_index=True)
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Другие объединения следуют аналогичному синтаксису.
Известные альтернативы
DataFrame.join по умолчанию - соединения по индексу. DataFrame.join по умолчанию выполняет ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ, поэтому здесь необходим how='inner'.
left.join(right, how='inner', lsuffix='_x', rsuffix='_y')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Обратите внимание, что мне нужно было указать аргументы lsuffix и rsuffix, поскольку в противном случае join выдает ошибку:
left.join(right)
ValueError: columns overlap but no suffix specified: Index(['value'], dtype='object')
Так как названия столбцов совпадают. Это не было бы проблемой, если бы они были названы по-другому.
left.rename(columns = {'value':'leftvalue'}).join(right, how='inner')
leftvalue value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
pd.concat присоединяется к индексу и может присоединяться к двум или более DataFrames одновременно. По умолчанию он выполняет полное внешнее соединение, поэтому здесь требуется how='inner'.
pd.concat([left, right], axis=1, sort=False, join='inner')
value value
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Для получения дополнительной информации о concat см. эта почта.
Чтобы выполнить внутреннее соединение с использованием индекса слева, столбец справа, вы будете использовать DataFrame.merge, комбинацию left_index=True и right_on=....
right2 = right.reset_index().rename({'idxkey' : 'colkey'}, axis=1)
right2
colkey value
0 B 0.543843
1 D 0.013135
2 E -0.326498
3 F 1.385076
left.merge(right2, left_index=True, right_on='colkey')
value_x colkey value_y
0 -0.402655 B 0.543843
1 -0.524349 D 0.013135
Другие объединения следуют аналогичной структуре. Обратите внимание, что только merge может выполнять объединение индекса в столбец. Вы можете объединить несколько столбцов при условии, что количество уровней индекса слева равно количеству столбцов справа.
join и concat не способны к смешанному слиянию. Вам нужно будет установить индекс в качестве предварительного шага, используя DataFrame.set_index.
Если ваш индекс назван, то из pandas> = 0.23, DataFrame.merge позволяет вам указать имя индекса для on (или left_on и right_on, если необходимо).
left.merge(right, on='idxkey')
value_x value_y
idxkey
B -0.402655 0.543843
D -0.524349 0.013135
Для предыдущего примера слияния с индексом левого столбца справа вы можете использовать left_on с именем индекса left:
left.merge(right2, left_on='idxkey', right_on='colkey')
value_x colkey value_y
0 -0.402655 B 0.543843
1 -0.524349 D 0.013135
Перейдите к другим темам в Pandas Merging 101, чтобы продолжить обучение:
* you are here
Эти анимации, возможно, лучше объяснят вам визуально. Кредиты: Garrick Aden-Buie tidyexplain репо
Это круто!
Это красивая диаграмма. Могу я спросить, как вы это сделали?