Merge, Join и Concat в Pandas

Оглавление

Библиотека 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().

Вернуться на верх