Page cover image

Группировка данных в Pandas с использованием cut и qcut

В этом руководстве вы научитесь бинировать данные в Python с помощью функций Pandas cut и qcut. Вы узнаете, почему бинирование — полезный навык в Pandas и как можно использовать его для лучшей группировки и отсеивания информации. К концу этого руководства вы научитесь:

  • Как использовать функции cut и qcut в Pandas

  • Когда использовать каждую из функций

  • Как изменять поведение этих функций для настройки создаваемых бинов

Содержание

Что такое бинирование в Pandas и Python?

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

В этом руководстве вы узнаете о двух разных методах Pandas, .cut() и .qcut(), для бинирования ваших данных. Эти методы позволят вам бинировать данные в бины пользовательского размера и бины равного размера соответственно. Бинары равного размера позволяют легко получать инсайты о распределении, а группировка данных в пользовательские бины может позволить получать инсайты о логических категориях.

Загрузка примерного DataFrame Pandas

Чтобы следовать за этим руководством, давайте используем очень простой DataFrame Pandas. Данные намеренно сохранены простыми для лучшего понимания того, как данные делятся. Набор данных имеет только две колонки: колонку имени и колонку возраста. Давайте загрузим данные с помощью метода .from_dict():

# Загрузка примерного DataFrame Pandas
import pandas as pd

df = pd.DataFrame.from_dict({
    'Name': ['Ray', 'Jane', 'Kate', 'Nik', 'Autumn', 'Kasi', 'Mandeep', 'Evan', 'Kyra', 'Jim'],
    'Age': [12, 7, 33, 34, 45, 65, 77, 11, 32, 55]
})

print(df.head())

# Возвращает:
      Name  Age
0     Ray   12
1    Jane    7
2    Kate   33
3     Nik   34
4  Autumn   45

В следующем разделе вы узнаете, как использовать метод Pandas .qcut() для бинирования данных в бины равного размера.

Pandas qcut: Бинаризация данных в бины равного размера

Метод Pandas .qcut() делит ваши данные на равные корзины на основе ранга или некоторых выборок квантилей. Этот процесс известен как квантильная дискретизация. Давайте рассмотрим параметры, доступные в функции:

# Параметры метода Pandas .qcut()
pd.qcut(
    x,                      # Колонка для бинирования
    q,                      # Количество квантилей
    labels=None,            # Список меток для включения
    retbins=False,          # Возвращать ли бины/метки
    precision=3,            # Точность для хранения и отображения меток бинов
    duplicates='raise'      # Если границы бинов не уникальны, поднимать ValueError
)

Функция имеет два обязательных параметра: колонка для бинирования (x=) и количество квантилей для генерации (q=). Функция возвращает Series данных, которые могут быть, например, присвоены новой колонке. Давайте посмотрим, как можно разделить колонку Age на четыре разных квантиля:

# Разделение колонки Age на четыре квантиля
df['Age Groups'] = pd.qcut(df['Age'], 4)
print(df.head())
# Возвращает:
#      Name  Age     Age Groups
# 0     Ray   12  (6.999, 17.0]
# 1    Jane    7  (6.999, 17.0]
# 2    Kate   33   (17.0, 33.5]
# 3     Nik   34   (33.5, 52.5]
# 4  Autumn   45   (33.5, 52.5]

На первый взгляд, новая колонка Age Groups может показаться немного странной. Давайте проведем немного времени, чтобы исследовать её. Сначала мы посмотрим на тип данных колонки, используя атрибут .dtype.

# Проверка типа данных колонки qcut
df['Age Groups'] = pd.qcut(df['Age'], 4)
print(df['Age Groups'].dtype)

# Возвращает: category

Тип данных, который возвращается, category — это очень экономичный способ для Pandas хранения категориальных данных. Давайте посмотрим, что означают реальные метки в колонке:

Изображение выше показывает, что квадратная скобка, [ или ], указывает на то, что точка данных включена в диапазон. Обычная скобка, такая как ( или ), указывает на то, что край не включен в группу.

Разделение данных на равные перцентили с использованием Pandas qcut

Вместо того чтобы просто указывать количество группировок, которые вы хотите создать, вы также можете передать список квартилей, которые вы хотите создать. Этот список должен представлять собой диапазон от 0 до 1, разбивая данные на равные проценты. Давайте посмотрим, как мы можем разбить наши данные на интервалы в 25%.

# Разделение колонки Age на 25% бины
df['Age Groups'] = pd.qcut(
   df['Age'],
   [0, 0.25, 0.5, 0.75, 1]
)
print(df.head())

# Возвращает:
#      Name  Age     Age Groups
# 0     Ray   12  (6.999, 17.0]
# 1    Jane    7  (6.999, 17.0]
# 2    Kate   33   (17.0, 33.5]
# 3     Nik   34   (33.5, 52.5]
# 4  Autumn   45   (33.5, 52.5]

Здесь видно, что это вернуло тот же результат, что и раньше. Наши данные разделены на четыре равных сегмента на основе диапазонов данных.

Добавление ярлыков к бинам в Pandas с помощью qcut

Сейчас наши категории данных описательны, но их немного сложно читать. Вы можете передать список меток, которые хотите использовать для переименования вашего набора данных. Длина списка должна соответствовать количеству создаваемых категорий. Давайте посмотрим, как мы можем преобразовать наши сгруппированные данные в описательные метки:

# Добавление меток к Pandas .qcut()
df['Age Groups'] = pd.qcut(
   df['Age'],
   [0, 0.25, 0.5, 0.75, 1],
   labels=['0-25%', '26-49%', '51-75%', '76-100%']
)
print(df.head())

# Возвращает:
#      Name  Age Age Groups
# 0     Ray   12      0-25%
# 1    Jane    7      0-25%
# 2    Kate   33     26-49%
# 3     Nik   34     51-75%
# 4  Autumn   45     51-75%

Это делает наш процесс биннинга в Pandas намного легче для понимания!

Изменение точности бина в Pandas с помощью qcut

Давайте вернемся к нашему предыдущему примеру, где мы просто передали q=4 для разделения данных на четыре квантиля. Аккуратно округленные интервалы выглядели так: (6.999, 17.0]. По умолчанию, Pandas использует аргумент precision=3, что приводит к отображению и хранению интервалов с точностью до трех знаков.

Хотя это более точно и аккуратно, часто выглядит не очень красиво. Давайте попробуем изменить точность на 1 и посмотрим, как теперь выглядят наши категории:

# Изменение точности в категориях
df['Age Groups'] = pd.qcut(
   df['Age'],
   4,
   precision=1
)
print(df.head())

# Возвращает:
#      Name  Age    Age Groups
# 0     Ray   12   (6.9, 17.0]
# 1    Jane    7   (6.9, 17.0]
# 2    Kate   33  (17.0, 33.5]
# 3     Nik   34  (33.5, 52.5]
# 4  Autumn   45  (33.5, 52.5]

В следующем разделе вы узнаете, как использовать метод cut из библиотеки Pandas для определения пользовательских интервалов данных

Pandas cut: группировка данных по пользовательским ячейкам

Функция cut в Pandas тесно связана с функцией .qcut(). Однако, она используется для разбиения значений на дискретные интервалы, которые вы определяете самостоятельно. Это может быть очень полезно, например, при определении значимых возрастных или доходных групп. Во многих случаях такие группировки имеют какое-то другое значение, например, юридическое или культурное.

Функция Pandas .cut() может технически давать такие же результаты, как и функция .qcut(), но также предоставляет значительно больший контроль над результатами. Давайте рассмотрим параметры этой функции:

pd.cut(
    x,                          # Входной массив для бинирования
    bins,                       # Бинарные корзины для использования: int (# бинов) или последовательность (ширины)
    right=True,                 # Включать ли правую границу
    labels=None,                # Метки для использования в бинах
    retbins=False,              # Возвращать ли бины или нет
    precision=3,                # Точность для хранения и отображения бинов
    include_lowest=False,       # Включать ли первый интервал или нет
    duplicates='raise',         # Что делать, если границы бинов не уникальны
    ordered=True                # Упорядочены ли метки
)

Функции .qcut() и .cut() имеют значительное количество схожих параметров. Однако функция cut предоставляет значительно больше возможностей. Например, как вы скоро узнаете, можно определить, как Pandas обрабатывает границы своих бинов.

Давайте посмотрим, как мы можем разделить столбец Возраст на три разные группы: младше восемнадцати, между 19 и 65, и 65 и старше.

# Разделение данных на пользовательские бины
df['Age Group'] = pd.cut(
   df['Age'],
   [0, 17, 64, 100]
)
print(df.head())

# Возвращает:
#      Name  Age Age Group
# 0     Ray   12   (0, 17]
# 1    Jane    7   (0, 17]
# 2    Kate   33  (17, 64]
# 3     Nik   34  (17, 64]
# 4  Autumn   45  (17, 64]

Вы можете видеть, что вы создали три отдельные возрастные группы. Как указано в скобках, значения варьируются от >0 до 17, >=18 до 64, >=65 до 100. В следующем разделе вы узнаете, как применить метки к этим группам.

Добавление меток к ячейкам в Pandas с помощью Cut

В этом разделе вы узнаете, как использовать параметр labels=, чтобы передавать список меток. Подобно функции qcut, метки должны быть такой же длины, как количество группировок.

Давайте добавим текстовые метки, чтобы упростить чтение группировок:

# Добавление меток к группировкам
df['Age Group'] = pd.cut(
    df['Age'],
    [0, 17, 64, 100],
    labels=['0-18 лет', '18-65 лет', '65+ лет']
)
print(df.head())

# Возвращает:
#      Name  Age        Age Group
# 0     Ray   12   0-18 лет
# 1    Jane    7   0-18 лет
# 2    Kate   33  18-65 лет
# 3     Nik   34  18-65 лет
# 4  Autumn   45  18-65 лет

Можно видеть, что эти результаты гораздо легче читать и интерпретировать!

Изменение поведения кромки в Pandas cut

По умолчанию, Pandas будет включать правую границу группы. Ранее, когда вы определяли границы [0, 17, 64, 100], это определяло следующие интервалы:

  • >0 to 17

  • >17 to 64

  • >64 to 100

В нашем примере это нормально, так как мы работаем с целыми значениями. Однако представьте, что наши возрасты определены как дробные значения, и у нас есть возраст 17.5. В нашем примере, так как возраст идет до (и включает) 17, значение 17.5 будет ошибочно включено в возрастную группу 18-64.

Мы можем использовать параметр right=, чтобы изменить это поведение. Аргумент по умолчанию равен True и указывает, что крайнее правое значение должно быть включено. Если мы изменим это значение на False, то диапазон будет включать все значения вплоть до (но не включая) этого значения.

Давайте создадим те же корзины, но с правым пределом исключа

# Использование аргумента right для изменения поведения бинирования
df['Age Group'] = pd.cut(
    df['Age'],
    [0, 18, 65, 100],
    labels=['0-18 лет', '18-65 лет', '65+ лет'],
    right=False
)
print(df.head())

# Возвращает:
#      Name  Age        Age Group
# 0     Ray   12   0-18 лет
# 1    Jane    7   0-18 лет
# 2    Kate   33  18-65 лет
# 3     Nik   34  18-65 лет
# 4  Autumn   45  18-65 лет

Изменение поведения первого интервала с помощью Pandas cut

По умолчанию Pandas не включает крайнее левое значение в интервал. В вышеупомянутом примере, если бы мы указали возраст 0, это значение не было бы учтено в интервале. Чтобы это значение вошло в интервал, можно использовать аргумент include_lowest= для изменения поведения.

По умолчанию аргумент будет использовать значение False. Изменение этого значения на True позволит включить самое левое значение. Давайте посмотрим, как это сделать:

# Включение левых значений
df['Age Group'] = pd.cut(
    df['Age'],
    [0, 18, 65, 100],
    labels=['0-18 лет', '18-65 лет', '65+ лет'],
    include_lowest=True
)
print(df.head())

# Возвращает:
#      Name  Age        Age Group
# 0     Ray   12   0-18 лет
# 1    Jane    7   0-18 лет
# 2    Kate   33  18-65 лет
# 3     Nik   34  18-65 лет
# 4  Autumn   45  18-65 лет

Создание упорядоченных категорий с помощью Pandas cut

Начиная с версии Pandas 1.1.0, функция cut будет возвращать упорядоченные категориальные бины. Это присваивает порядок значениям этой категории. Давайте посмотрим, как это поведение выглядит при использовании стандартных настроек.

# Создание упорядоченных категорий
print(pd.cut(
    df['Age'],
    [0, 18, 65, 100],
    labels=['0-18 лет', '18-65 лет', '65+ лет'],
    ordered=True
))

# Возвращает:
# 0     0-18 лет
# 1     0-18 лет
# 2    18-65 лет
# 3    18-65 лет
# 4    18-65 лет
# 5    18-65 лет
# 6      65+ лет
# 7     0-18 лет
# 8    18-65 лет
# 9    18-65 лет
# Name: Age, dtype: category
# Categories (3, object): ['0-18 лет' < '18-65 лет' < '65+ лет']

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

Изменение поведения на ordered=False убирает эту иерархию, если она вам не нужна.

Упражнения

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

Вопрос 1

Создайте группировки, охватывающие 0-24,9%, 25-49,9%, 51-74,9% и 100% диапазона данных. Сохраните значение 0% включенным в самый низкий диапазон.

Поскольку функция .qcut() не позволяет указать включение наименьшего значения диапазона, необходимо использовать функцию

df['Age Group'] = pd.cut(
    df['Age'], 
    [0, 0.25, 0.5, 0.75, 1], 
    include_lowest=True,
    right=False
)
Вопрос 2

Какова польза от упорядочивания категорий?

Категории, хотя они выглядят как строки, не являются строками, их сортировка может работать некорректно. Чтобы эти значения сортировались правильно, включите порядок в ваши категории.

Вопрос 3

Использование функции cut и qcut для бинирования данных

Функция cut позволяет вам определять свои собственные числовые диапазоны, в то время как функция qcut обеспечивает равномерное распределение элементов в бинах.

Пример использования функции cut

# Разделение данных на пользовательские бины
df['Age Group'] = pd.cut(
    df['Age'],
    [0, 18, 65, 100],
    labels=['0-18 лет', '18-65 лет', '65+ лет']
)
print(df.head())

# Возвращает:
#      Name  Age        Age Group
# 0     Ray   12   0-18 лет
# 1    Jane    7   0-18 лет
# 2    Kate   33  18-65 лет
# 3     Nik   34  18-65 лет
# 4  Autumn   45  18-65 лет

Пример использования функции qcut

# Разделение данных на равные бины
df['Age Groups'] = pd.qcut(
    df['Age'],
    4,
    labels=['0-25%', '26-50%', '51-75%', '76-100%']
)
print(df.head())

# Возвращает:
#      Name  Age     Age Groups
# 0     Ray   12  0-25%
# 1    Jane    7  0-25%
# 2    Kate   33  26-50%
# 3     Nik   34  51-75%
# 4  Autumn   45  51-75%

Заключение и резюме

В этом уроке вы узнали, как разбивать ваши данные на категории в Python и Pandas, используя функции cut и qcut. Ниже приведен краткий обзор того, что вы изучили:

  • Функция qcut в Pandas разбивает данные на равные группы элементов.

  • Функция cut в Pandas позволяет задавать собственные диапазоны данных.

  • Разбиение данных на бины позволяет лучше понять распределение данных, а также создавать логические категории на основе других абстракций.

  • Обе функции обеспечивают гибкость в определении и отображении ваших контейнеров.

Дополнительные ресурсы

Чтобы узнать больше связанных тем, ознакомьтесь с руководствами ниже:

  • Python Defaultdict: Обзор и примеры

  • Pandas GroupBy: группировка, суммирование и агрегация данных в Python

  • Pandas Describe: Описательная статистика для вашего DataFrame

Last updated