20 примеров для освоения слияния датафреймов данных в Python Pandas

Слияние позволяет объединить данные из разных источников в единую структуру. Это необходимая операция при работе с табличными данными, поскольку невозможно или нецелесообразно хранить все данные в одной таблице данных или DataFrame.

Понимание того, как эффективно объединять DataFrames в Pandas, является важнейшим навыком для любого специалиста по анализу данных или аналитика.

Слияние означает объединение DataFrames на основе значений в общем столбце или столбцах.

20 примеров для освоения слияния датафреймов данных в Python Pandas

В этой статье мы рассмотрим полный набор из 20 примеров, которые раскроют нюансы операций слияния. Мы начнем с базовых функций слияния и постепенно перейдем к более сложным сценариям, охватывая все детали слияния DataFrames с помощью Pandas.

Мы рассмотрим следующие функции:

  • merge
  • merge_asof
  • merge_ordered

Давайте начнем с создания двух DataFrames, которые будут использоваться в примерах.

import numpy as np
import pandas as pd


names = pd.DataFrame(
    
    {
        "id": [1, 2, 3, 4, 10],
        "name": ["Emily", "Jane", "Joe", "Matt", "Lucas"],
        "age": np.random.randint(20, 30, size=5)
    }
    
)

scores = pd.DataFrame(
    
    {
        "id": np.arange(1, 8),
        "score": np.random.randint(80, 100, size=7),
        "group": list("ABCAACA")
    }
    
)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 1

Основной синтаксис функции слияния выглядит следующим образом. Параметр on указывает столбец или столбцы, которые будут использоваться при сравнении строк.

merged_df = names.merge(scores, on="id")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 2 – как параметр

Существуют различные типы слияния. Параметр how определяет один из следующих типов:

  • left: использовать только ключи из левого DataFrame
  • right: использовать только ключи из правого DataFrame
  • внешний: использовать объединение ключей из обоих DataFrame
  • внутренний: использовать пересечение ключей из обоих DataFrame
  • cross: создает картезианское произведение из обоих DataFrames

По умолчанию параметр how имеет значение inner, поэтому в предыдущем примере объединенный DataFrame содержит пересечение ключей.

Ключи – это значения в столбце(ах), указанном(ых) параметром on.

Давайте выполним слияние слева.

merged_df = names.merge(scores, on="id", how="left")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Объединенный DataFrame включает все ключи из левого DataFrame. Несовпадающие строки заполняются NaN, стандартным представлением отсутствующего значения.

Пример 3 – правое слияние

Это противоположность левому слиянию, но я бы не рекомендовал использовать правое слияние, поскольку его можно достичь, изменив порядок DataFrames и используя левое слияние.

# followings are the same
merged_df = names.merge(scores, on="id", how="left")
merged_df = scores.merge(names, on="id", how="right")

Пример 4- внешнее слияние

merged_df = names.merge(scores, on="id", how="outer")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Объединенный фрейм данных включает все ключи из обоих фреймов данных.

Пример 5- параметр индикатора

Параметр indicator создает столбец в объединенном DataFrame, который указывает, откуда берется ключевое значение в строках.

  • both: значение ключа существует в обоих DataFrames
  • left_only: только левый DataFrame
  • right_only: только правый DataFrame
merged_df = names.merge(scores, on="id", how="outer", indicator=True)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 6 – параметр индикатора

Параметр indicator также принимает в качестве аргумента строковое значение, которое используется в качестве имени колонки.

merged_df = names.merge(scores, on="id", how="left", indicator="source")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 7 – параметры left_on и right_on

Если столбцы, используемые для объединения DataFrames, имеют разные имена, мы можем использовать параметры left_on и right_on.

# rename the id column in the scores DataFrame
scores = scores.rename(columns={"id": "id_number"})

merged_df = names.merge(scores, left_on="id", right_on="id_number")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 8 – слияние по нескольким столбцам

Для этого примера мы создадим два новых DataFrames.

products = pd.DataFrame(
    
    {
        "pg": ["A", "A", "A", "B", "B", "B"],
        "id": [101, 102, 103, 101, 102, 104],
        "price": np.random.randint(50, 80, size=6),
        "cost": np.random.randint(40, 50, size=6),
        "discount": [0.1, 0.1, 0, 0, 0.2, 0]
    }
    
)

sales = pd.DataFrame(
    
    {
        "pg": ["A", "A", "A", "B", "B", "B"],
        "id": [101, 102, 105, 101, 102, 106],
        "sales_qty": np.random.randint(1, 10, size=6),
        "discount": [0, 0.1, 0.1, 0.2, 0, 0]
    }
    
)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Чтобы объединить DataFrames по нескольким столбцам, мы записываем имена столбцов в виде списка Python.

merged_df = products.merge(sales, on=["pg", "id"])
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 9 – параметр суффикса

В предыдущем примере объединенный DataFrame имеет столбцы discount_x и discount_y . Суффиксы x и y добавляются для разделения столбцов, которые существуют в обоих DataFrame с одинаковым именем. Суффикс x используется для левого DataFrame, а y – для правого.

Мы можем использовать собственные суффиксы, чтобы сделать вывод более понятным.

merged_df = products.merge(sales, on=["pg", "id"], suffixes=["_products", "_sales"])
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 10 – несколько столбцов

Как и параметр on, параметры right_on и left_on принимают в качестве аргумента список в случае, если имена столбцов отличаются.

# rename the id column
sales = sales.rename(columns={"id": "product_id"})

merged_df = products.merge(
    sales, 
    left_on=["pg", "id"], 
    right_on=["pg", "product_id"],
    how="left",
    suffixes=["_products", "_sales"]
)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 11 – слияние по индексу

Мы также можем объединять DataFrames по значениям их индексов. Для этого примера мы создадим два новых DataFrames.

df1 = pd.DataFrame(
    np.random.randint(0, 10, size=(5, 4)),
    columns=list("ABCD")
)

df2 = pd.DataFrame(
    np.random.randint(0, 10, size=(5, 4)),
    columns=list("EFGH"),
    index=[2, 3, 4, 5, 6]
)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Как мы видим на скриншоте выше, DataFrames имеют разные значения индекса. Один начинается с 0, а другой – с 2.

Для объединения по индексу мы используем параметры left_index и right_index.

merged_df = df1.merge(df2, left_index=True, right_index=True)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Поскольку мы использовали внутреннее слияние, объединенный DataFrame включает только те индексы, которые существуют в обоих DataFrame.

Пример 12 – как параметр с объединением по индексу

Мы можем использовать параметр how и при объединении по индексам.

merged_df = df1.merge(df2, left_index=True, right_index=True, how="left")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Пример 13 – объединение данных временных рядов

Данные временных рядов могут включать измерения, сделанные в очень короткие периоды времени (например, на уровне секунд). Поэтому, когда мы объединяем два DataFrames, состоящих из данных временного ряда, мы можем столкнуться с измерениями, отличающимися на секунду или две.

Для таких случаев Pandas предоставляет “умный” способ слияния с помощью функции merge_asof.

Предположим, что мы объединяем DataFrame A и B. Если строка в левом DataFrame не имеет соответствующей строки в правом DataFrame, merge_asof позволяет взять строку, значение которой близко к значению в левом DataFrame.

Это похоже на слияние слева, за исключением того, что мы сравниваем по ближайшему ключу, а не по одинаковым ключам. Оба DataFrames должны быть отсортированы по ключу.

Для каждой строки в левом DataFrame:

  • При поиске “назад” выбирается последняя строка в правом DataFrame, ключ ‘on’ которой меньше или равен ключу левого DataFrame.
  • При поиске “вперед” выбирается первая строка правого DataFrame, ключ ‘on’ которой больше или равен ключу левого DataFrame.
  • При “ближайшем” поиске выбирается строка в правом DataFrame, чей ключ ‘on’ ближе всего по абсолютному расстоянию к левому ключу.

Давайте создадим два новых DataFrames, содержащих данные временных рядов.

df1 = pd.DataFrame(
    
    {
        "time": pd.date_range(start="2022-12-09", periods=7, freq="2S"),
        "left_value": np.round(np.random.random(7), 2)
    }

)

df2 = pd.DataFrame(
    
    {
        "time": pd.date_range(start="2022-12-09", periods=6, freq="3S"),
        "right_value": np.round(np.random.random(6), 2)
    }

)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Некоторые значения в столбце времени совпадают, в то время как другие отличаются на несколько секунд.

Давайте посмотрим, что произойдет, если мы объединим их.

merged_df = pd.merge_asof(df1, df2, on="time")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Правый DataFrame (df2) не имеет значения 00:00:02, поэтому в объединенном DataFrame значение 00:00:00 используется в качестве правого значения.

Пример 14 – параметр направления

В предыдущем примере функция merge_asof искала предыдущее значение для несовпадающих строк, поскольку значение параметра направления по умолчанию – “назад”.

Давайте изменим его на “ближайшее” и посмотрим, что произойдет.

merged_df = pd.merge_asof(df1, df2, on="time", direction="nearest")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Правое значение в первой строке равно 0,36, потому что следующее значение (00:00:03) ближе к значению в левом DataFrame (00:00:02), чем предыдущее (00:00:00).

Пример 15 – параметр допуска

Можно также задать допуск, который будет использоваться при проверке предыдущего и следующего значений.

В следующем примере направление – вперед, поэтому следующее значение проверяется на несовпадение строк. Мы также установили допуск в 1 секунду, поэтому для использования следующего значения оно должно отличаться не более чем на 1 секунду.

merged_df = pd.merge_asof(
    df1, 
    df2, 
    on="time", 
    direction="forward", 
    tolerance=pd.Timedelta("1s")
)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Посмотрите на третью и шестую строки в объединенном DataFrame. Правое значение равно NaN, потому что следующее значение в правом DataFrame для этих строк отличается на 2 секунды.

  • слева: 00:00:04, следующее значение справа: 00:00:06
  • слева: 00:00:10, следующее значение справа: 00:00:12

Пример 16 – параметр allow_exact_matches

У нас также есть возможность не разрешать точные совпадения в объединенном DataFrame. По умолчанию точные совпадения присутствуют в объединенном DataFrame, но это можно изменить с помощью параметра allow_exact_matches.

merged_df = pd.merge_asof(df1, df2, on="time", allow_exact_matches=False)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Значения времени в первых строках одинаковы, но объединенный DataFrame имеет значение NaN в первой строке правой колонки значений, потому что мы установили значение параметра allow_exact_matches как False.

Пример 17 – по параметру

Параметр by можно использовать для разделения групп при объединении точек данных с предыдущим или следующим значением.

Давайте добавим столбец группы в наши DataFrames.

df1["group"] = ["AA"] * 4 + ["BB"] * 3

df2["group"] = ["AA"] * 3 + ["BB"] * 3
20 примеров для освоения слияния датафреймов данных в Python Pandas

Допустим, мы хотим использовать merge_asof, но только внутри групп, чтобы значения в определенной группе не могли быть объединены с любыми значениями в другой группе. Для этого мы можем использовать параметр by.

merged_df = pd.merge_asof(df1, df2, on="time", by="group")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Правое значение в первой строке для группы BB – NaN . Мы объединяем на основе “обратного” направления, и предыдущее значение принадлежит другой группе.

Пример 18 – упорядоченное слияние

Функция merge_ordered выполняет слияние для упорядоченных данных с необязательным заполнением/интерполяцией. Она предназначена для упорядоченных данных, таких как временные ряды.

Ее легче понять на примере:

merged_df = pd.merge_ordered(df1, df2)
20 примеров для освоения слияния датафреймов данных в Python Pandas

Строки упорядочены по столбцу времени. Если один из DataFrames не имеет определенного значения времени, столбцы, исходящие из него, заполняются значением NaN .

Пример 19 – параметр fill_method

При выполнении упорядоченного слияния с помощью merge_ordered , мы можем использовать параметр fill_method для определения метода интерполяции.

Значение по умолчанию – NaN, и единственная опция, которую мы можем использовать, это “ffill”, что означает прямое заполнение.

merged_df = pd.merge_ordered(df1, df2, fill_method="ffill")
20 примеров для освоения слияния датафреймов данных в Python Pandas

Сравните результат с предыдущим примером, и вы заметите, как значения NaN заменяются предыдущим значением.

Пример 20- параметр left_by

Мы также можем выполнить упорядоченное слияние в каждой группе отдельно. Параметр left_by группирует левый DataFrame по столбцам группы и объединяет по частям с правым DataFrame.

merged_df = pd.merge_ordered(df1, df2, fill_method="ffill", left_by="group")
20 примеров для освоения слияния датафреймов данных в Python Pandas

В отличие от предыдущего примера, правое значение в первой строке группы “BB” – NaN, потому что мы не можем использовать значения из другой группы.

Заключительные слова

В этих 20 примерах мы рассмотрели различные сценарии слияния, от самых простых до более сложных. Благодаря этим практическим примерам вы будете готовы к решению любой задачи по объединению, которая встанет перед вами.

Спасибо, что читаете!

+1
0
+1
1
+1
0
+1
0
+1
0

Ответить

Ваш адрес email не будет опубликован. Обязательные поля помечены *