Merge, Join и Concat в Pandas
Оглавление
- Когда использовать метод Pandas concat против merge и join
- Как использовать метод concat в Pandas
- Использование методов Pandas merge и join для объединения DataFrames
- Заключение
Библиотека Pandas в Python является популярной библиотекой для очистки, манипулирования и интерпретации больших объемов данных. В одной из предыдущих статей мы рассмотрели основополагающую структуру Pandas - DataFrame. Если вы не знакомы с фреймами данных Pandas, посмотрите эту статью, чтобы понять основы.
В этой заметке мы научимся объединять несколько DataFrames с помощью Pandas merge
, join
и concat
. Эти методы позволяют увеличить объем данных за счет склеивания данных из различных источников.
Мы рассмотрим:
- Когда использовать
concat
, а когдаmerge
илиjoin
; - Как использовать метод
concat
Pandas; - Как использовать методы
merge
иjoin
Pandas.
Давайте начнем.
Когда использовать панды concat
против merge
и join
Хотя merge
, join
и concat
работают для объединения нескольких DataFrames, они используются для совершенно разных целей. В этом разделе мы узнаем, в каких случаях необходимо использовать одну операцию, а в каких - другую. Ключевое различие заключается в том, как объединять фреймы данных - горизонтально или вертикально.
Метод concat
позволяет объединять DataFrames вертикально.
Представьте, что у вас есть два DataFrames с одинаковыми столбцами. Возможно, первый DataFrame содержит 10 строк данных о торговле акциями для одной акции, а второй DataFrame - 10 строк данных о торговле акциями для другой акции. Вертикальная комбинация использует метод concat
DataFrame для объединения двух DataFrame в один DataFrame с двадцатью строками.
Обратите внимание, что в вертикальной комбинации с concat
количество строк увеличилось, а количество столбцов осталось прежним.
Напротив, методы merge
и join
помогают объединить DataFrames по горизонтали.
Представьте, что у вас есть два фрейма DataFrames. Первый содержит информацию о торговле акциями различных компаний. Второй содержит информацию о штаб-квартире и количестве сотрудников конкретной компании. Если у двух DataFrames есть одно общее поле, например, символ акции или название компании, то можно объединить их таким образом, чтобы каждая строка содержала как данные о торговле акциями, так и справочную информацию о компании.
Обратите внимание, что в этой горизонтальной комбинации мы не добавляем никаких дополнительных строк. Скорее, мы добавляем столбцы к существующим строкам. Горизонтальная комбинация из операции merge
аналогична оператору JOIN
в SQL.
Теперь, когда мы понимаем разницу между вертикальными комбинациями с concat
и горизонтальными с merge
или join
, давайте более подробно рассмотрим, как использовать эти методы.
Как использовать метод concat
Pandas
В нашей предыдущей статье, посвященной Pandas DataFrames, мы использовали пример фондовых данных, чтобы показать создание, изучение и работу с DataFrames. Мы использовали примеры данных о торговле акциями Amazon ("AMZN"), Apple ("AAPL") и Google ("GOOG").
Представьте, что у нас есть второй набор данных с торговой информацией еще по двум компаниям - Facebook ("FB") и Tesla ("TSLA"). Эти DataFrames имеют одинаковую форму, поэтому было бы полезно объединить их, чтобы оперировать ими вместе.
С помощью метода concat
мы можем сделать это следующим образом:
>>> import pandas as pd
>>> stocks = pd.read_csv('https://gist.githubusercontent.com/alexdebrie/b3f40efc3dd7664df5a20f5eee85e854/raw/ee3e6feccba2464cbbc2e185fb17961c53d2a7f5/stocks.csv')
>>> stocks.info()
< class 'pandas.core.frame.DataFrame'>
RangeIndex: 15 entries, 0 to 14
Data columns (total 7 columns):
date 15 non-null object
symbol 15 non-null object
open 15 non-null float64
high 15 non-null float64
low 15 non-null float64
close 15 non-null float64
volume 15 non-null int64
dtypes: float64(4), int64(1), object(2)
memory usage: 920.0+ bytes
>>> stocks2 = pd.read_csv('https://gist.githubusercontent.com/alexdebrie/53ebac036b404875ef8e981c0cbd0901/raw/6c70336130eb7e45cec167ee7cd52d15baa392ea/stocks2.csv')
>>> combined = pd.concat([stocks, stock2], ignore_index=True)
>>> combined
date symbol open high low close volume
0 2019-03-01 AMZN 1655.13 1674.2600 1651.00 1671.73 4974877
1 2019-03-04 AMZN 1685.00 1709.4300 1674.36 1696.17 6167358
2 2019-03-05 AMZN 1702.95 1707.8000 1689.01 1692.43 3681522
3 2019-03-06 AMZN 1695.97 1697.7500 1668.28 1668.95 3996001
4 2019-03-07 AMZN 1667.37 1669.7500 1620.51 1625.95 4957017
5 2019-03-01 AAPL 174.28 175.1500 172.89 174.97 25886167
6 2019-03-04 AAPL 175.69 177.7500 173.97 175.85 27436203
7 2019-03-05 AAPL 175.94 176.0000 174.54 175.53 19737419
8 2019-03-06 AAPL 174.67 175.4900 173.94 174.52 20810384
9 2019-03-07 AAPL 173.87 174.4400 172.02 172.50 24796374
10 2019-03-01 GOOG 1124.90 1142.9700 1124.75 1140.99 1450316
11 2019-03-04 GOOG 1146.99 1158.2800 1130.69 1147.80 1446047
12 2019-03-05 GOOG 1150.06 1169.6100 1146.19 1162.03 1443174
13 2019-03-06 GOOG 1162.49 1167.5700 1155.49 1157.86 1099289
14 2019-03-07 GOOG 1155.72 1156.7600 1134.91 1143.30 1166559
15 2019-03-01 FB 162.60 163.1320 161.69 162.28 11097770
16 2019-03-04 FB 163.90 167.5000 163.83 167.37 18894689
17 2019-03-05 FB 167.37 171.8800 166.55 171.26 28187890
18 2019-03-06 FB 172.90 173.5700 171.27 172.51 21531723
19 2019-03-07 FB 171.50 171.7400 167.61 169.13 18306504
20 2019-03-01 TSLA 306.94 307.1300 291.90 294.79 22911375
21 2019-03-04 TSLA 298.12 299.0000 282.78 285.36 17096818
22 2019-03-05 TSLA 282.00 284.0000 270.10 276.54 18764740
23 2019-03-06 TSLA 276.48 281.5058 274.39 276.24 10335485
24 2019-03-07 TSLA 278.84 284.7000 274.25 276.59 9442483
В приведенном выше примере мы создаем наш первый DataFrame и с помощью метода info видим, что в нашем DataFrame 15 строк и семь столбцов. Затем мы создаем второй DataFrame и объединяем его с первым DataFrame с помощью метода concat
. После этого мы видим, что наш DataFrame содержит информацию обо всех пяти компаниях в двух DataFrame.
Если мы с помощью метода info посмотрим на наш новый DataFrame, то увидим, что в нем по-прежнему семь столбцов, но теперь в нем 25 строк - комбинация двух DataFrame.
>>> combined.info()
< class 'pandas.core.frame.DataFrame'>
Int64Index: 25 entries, 0 to 9
Data columns (total 7 columns):
date 25 non-null object
symbol 25 non-null object
open 25 non-null float64
high 25 non-null float64
low 25 non-null float64
close 25 non-null float64
volume 25 non-null int64
dtypes: float64(4), int64(1), object(2)
memory usage: 1.6+ KB
Метод concat
является отличным способом объединения нескольких DataFrames, содержащих одинаковые формы данных. Обратите внимание, что столбцы не обязательно должны полностью совпадать - для столбцов, не имеющих значений, Пандас просто включит нулевое значение.
Использование merge
и join
в Pandas для объединения DataFrames
Методы merge
и join
представляют собой пару методов для горизонтального объединения DataFrames с Pandas. Это отличный способ обогатить один DataFrame данными из другого DataFrame.
Оба метода merge
и join
работают аналогично, но метод join
является методом удобства, облегчающим объединение DataFrames. Фактически, join
использует merge
под капотом. Я предпочитаю использовать join
там, где это возможно, так как это несколько более простой синтаксис.
При использовании merge
или join
необходимо указать как следует объединять или соединять DataFrames. Существует четыре возможных значения для способа объединения двух DataFrames:
- Left: Сохраняем все строки для первого DataFrame и обогащаем столбцами из второго DataFrame, если они совпадают по столбцам, по которым нужно объединить;
- Right: То же, что и левый, но в обратном порядке - сохраняем все строки для второго DataFrame и обогащаем столбцами из совпадений в первом DataFrame.
- Inner: Сохраняется только пересечение двух DataFrames - строки, в которых есть значения в обоих DataFrames для столбцов, по которым выполняется объединение.
- Outer: Сохраняются все строки из обоих DataFrames, независимо от того, есть ли совпадающие строки в другом DataFrame.
Эти четыре типа соединений совпадают с четырьмя типами соединений SQL. Обратите внимание, что значение по умолчанию для how в методе merge
- внутреннее, а значение по умолчанию для how в методе join
- левое. В общем случае для наглядности лучше явно указать тип соединения.
Чтобы понять, как работают различные типы объединений, рассмотрим несколько примеров.
Использование левого объединения с помощью метода Pandas join
Сначала рассмотрим, как использовать тип left join. Мы продолжим использовать наши объединенные данные по акциям из раздела concat
выше. Представьте, что мы хотим обогатить эти данные справочной информацией о компании, например, о количестве ее сотрудников, а также о том, где находится ее штаб-квартира.
Давайте загрузим справочную информацию о нашей компании, а затем соединим ее с торговыми данными с помощью левого соединения.
>>> companies = pd.read_csv('https://gist.githubusercontent.com/alexdebrie/90954a10bbdebd89185f7b4d340563cd/raw/d91744e599356b7a52b9c027751d4613c06c5f40/companies.csv')
>>> companies
symbol employees headquarters_city headquarters_state
0 AMZN 613300 Seattle WA
1 GOOG 98771 Mountain View CA
2 AAPL 132000 Cupertino CA
>>> enriched = combined.join(companies.set_index('symbol'), on='symbol', how='left')
>>> enriched
date symbol open high low close volume employees headquarters_city headquarters_state
0 2019-03-01 AMZN 1655.13 1674.2600 1651.00 1671.73 4974877 613300.0 Seattle WA
1 2019-03-04 AMZN 1685.00 1709.4300 1674.36 1696.17 6167358 613300.0 Seattle WA
2 2019-03-05 AMZN 1702.95 1707.8000 1689.01 1692.43 3681522 613300.0 Seattle WA
3 2019-03-06 AMZN 1695.97 1697.7500 1668.28 1668.95 3996001 613300.0 Seattle WA
4 2019-03-07 AMZN 1667.37 1669.7500 1620.51 1625.95 4957017 613300.0 Seattle WA
5 2019-03-01 AAPL 174.28 175.1500 172.89 174.97 25886167 132000.0 Cupertino CA
6 2019-03-04 AAPL 175.69 177.7500 173.97 175.85 27436203 132000.0 Cupertino CA
7 2019-03-05 AAPL 175.94 176.0000 174.54 175.53 19737419 132000.0 Cupertino CA
8 2019-03-06 AAPL 174.67 175.4900 173.94 174.52 20810384 132000.0 Cupertino CA
9 2019-03-07 AAPL 173.87 174.4400 172.02 172.50 24796374 132000.0 Cupertino CA
10 2019-03-01 GOOG 1124.90 1142.9700 1124.75 1140.99 1450316 98771.0 Mountain View CA
11 2019-03-04 GOOG 1146.99 1158.2800 1130.69 1147.80 1446047 98771.0 Mountain View CA
12 2019-03-05 GOOG 1150.06 1169.6100 1146.19 1162.03 1443174 98771.0 Mountain View CA
13 2019-03-06 GOOG 1162.49 1167.5700 1155.49 1157.86 1099289 98771.0 Mountain View CA
14 2019-03-07 GOOG 1155.72 1156.7600 1134.91 1143.30 1166559 98771.0 Mountain View CA
15 2019-03-01 FB 162.60 163.1320 161.69 162.28 11097770 NaN NaN NaN
16 2019-03-04 FB 163.90 167.5000 163.83 167.37 18894689 NaN NaN NaN
17 2019-03-05 FB 167.37 171.8800 166.55 171.26 28187890 NaN NaN NaN
18 2019-03-06 FB 172.90 173.5700 171.27 172.51 21531723 NaN NaN NaN
19 2019-03-07 FB 171.50 171.7400 167.61 169.13 18306504 NaN NaN NaN
20 2019-03-01 TSLA 306.94 307.1300 291.90 294.79 22911375 NaN NaN NaN
21 2019-03-04 TSLA 298.12 299.0000 282.78 285.36 17096818 NaN NaN NaN
22 2019-03-05 TSLA 282.00 284.0000 270.10 276.54 18764740 NaN NaN NaN
23 2019-03-06 TSLA 276.48 281.5058 274.39 276.24 10335485 NaN NaN NaN
24 2019-03-07 TSLA 278.84 284.7000 274.25 276.59 9442483 NaN NaN NaN
Давайте рассмотрим, что здесь происходит.
Сначала мы загрузим наш DataFrame компании с URL-адреса. Когда мы смотрим на этот фрейм, то видим, что в нем есть данные для трех наших компаний -AMZN, AAPL и GOOG, но нет для двух других -BB и TSLA.
Затем мы используем метод join()
для объединения наших двух DataFrames. Для этого мы используем левое объединение и указываем, что объединение должно происходить по столбцу symbol
, который является общим для обоих DataFrames.
После завершения объединения мы выводим на печать DataFrame. Видно, что в нем осталось 25 строк из исходного DataFrame и что некоторые из этих строк были дополнены информацией о штаб-квартире компании и количестве сотрудников. Однако во втором DataFrame остались те строки, которые не содержали соответствующей информации.
Использование внутреннего объединения с помощью метода Pandas join
Теперь посмотрим, как те же два DataFrames будут объединены при использовании внутреннего соединения.
>>> enriched_inner = combined.join(companies.set_index('symbol'), on='symbol', how='inner')
>>> enriched_inner
date symbol open high low close volume employees headquarters_city headquarters_state
0 2019-03-01 AMZN 1655.13 1674.26 1651.00 1671.73 4974877 613300 Seattle WA
1 2019-03-04 AMZN 1685.00 1709.43 1674.36 1696.17 6167358 613300 Seattle WA
2 2019-03-05 AMZN 1702.95 1707.80 1689.01 1692.43 3681522 613300 Seattle WA
3 2019-03-06 AMZN 1695.97 1697.75 1668.28 1668.95 3996001 613300 Seattle WA
4 2019-03-07 AMZN 1667.37 1669.75 1620.51 1625.95 4957017 613300 Seattle WA
5 2019-03-01 AAPL 174.28 175.15 172.89 174.97 25886167 132000 Cupertino CA
6 2019-03-04 AAPL 175.69 177.75 173.97 175.85 27436203 132000 Cupertino CA
7 2019-03-05 AAPL 175.94 176.00 174.54 175.53 19737419 132000 Cupertino CA
8 2019-03-06 AAPL 174.67 175.49 173.94 174.52 20810384 132000 Cupertino CA
9 2019-03-07 AAPL 173.87 174.44 172.02 172.50 24796374 132000 Cupertino CA
10 2019-03-01 GOOG 1124.90 1142.97 1124.75 1140.99 1450316 98771 Mountain View CA
11 2019-03-04 GOOG 1146.99 1158.28 1130.69 1147.80 1446047 98771 Mountain View CA
12 2019-03-05 GOOG 1150.06 1169.61 1146.19 1162.03 1443174 98771 Mountain View CA
13 2019-03-06 GOOG 1162.49 1167.57 1155.49 1157.86 1099289 98771 Mountain View CA
14 2019-03-07 GOOG 1155.72 1156.76 1134.91 1143.30 1166559 98771 Mountain View CA
Наш код join
полностью повторяет предыдущий раздел, за исключением того, что мы перешли от левого к внутреннему соединению. Когда мы распечатываем DataFrame, то видим разницу - в нашем объединенном DataFrame всего пятнадцать строк. Десять строк FB и TSLA, которым не нашлось соответствия в DataFrame наших компаний, были полностью удалены, а не включены нулевые значения для отсутствующих столбцов.
Тип соединения, который вы хотите использовать, зависит от вашего сценария использования. В этих двух примерах мы узнали, как тип объединения влияет на то, какие строки будут сохранены в операции join
.
Заключение
В этом посте мы узнали, как объединять DataFrames в Pandas. Мы узнали, что существует два типа объединения DataFrames - по горизонтали и по вертикали. Затем мы рассмотрели примеры объединения по вертикали с помощью concat()
и по горизонтали с помощью join()
или merge()
. Наконец, мы узнали о различных типах объединений с использованием join()
или merge()
.