Ранжирование значений
Присваивайте значениям столбца ранги с помощью rank(), выбирайте способы разрешения одинаковых значений и создавайте интервалы процентилей с помощью pd.cut().
«Ранжирование значений» — бесплатный урок Pandas & NumPy Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Pandas & NumPy Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Что такое ранжирование?
Ранжирование присваивает каждому значению Series позицию на основе его относительной величины: ранг 1 — наименьшему значению, ранг n — наибольшему (или наоборот). В отличие от сортировки, которая переупорядочивает строки, rank() добавляет новый столбец с порядковыми позициями рядом с исходными данными. Ранги используются в таблицах лидеров, при вычислении процентилей и в некоторых статистических тестах, требующих порядковой позиции, а не абсолютных значений.
import pandas as pd
df = pd.DataFrame({
'player': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve'],
'score': [88, 72, 95, 72, 85]
})
df['rank'] = df['score'].rank()
print(df)
# player score rank
# 0 Alice 88 4.0
# 1 Bob 72 1.5 <- tied with Dave
# 2 Carol 95 5.0
# 3 Dave 72 1.5 <- tied with Bob
# 4 Eve 85 3.0Ранг по возрастанию и по убыванию
По умолчанию rank() присваивает ранг 1 наименьшему значению (по возрастанию). Чтобы присвоить ранг 1 наибольшему значению (например, первому месту в соревновании), передайте ascending=False. Это соответствует принятому в спорте, таблицах лидеров и рейтингах продаж правилу: «первое место = самый высокий результат».
import pandas as pd
df = pd.DataFrame({'score': [70, 95, 85, 60, 90]})
# Rank 1 = highest score
df['competition_rank'] = df['score'].rank(ascending=False)
print(df)
# score competition_rank
# 0 70 4.0
# 1 95 1.0
# 2 85 3.0
# 3 60 5.0
# 4 90 2.0Методы разрешения равенства рангов
Когда несколько строк имеют одинаковое значение (ничья), параметр method определяет, как присваиваются ранги. Доступны следующие варианты: 'average' (по умолчанию — связанные строки получают средний ранг), 'min' (все связанные строки получают наименьший ранг), 'max' (все получают наибольший ранг), 'first' (строка, расположенная первой, получает меньший ранг) и 'dense' (после одинаковых рангов номера рангов не пропускаются).
import pandas as pd
s = pd.Series([10, 20, 20, 30])
print('average:', s.rank(method='average').tolist()) # [1.0, 2.5, 2.5, 4.0]
print('min: ', s.rank(method='min').tolist()) # [1.0, 2.0, 2.0, 4.0]
print('max: ', s.rank(method='max').tolist()) # [1.0, 3.0, 3.0, 4.0]
print('first: ', s.rank(method='first').tolist()) # [1.0, 2.0, 3.0, 4.0]
print('dense: ', s.rank(method='dense').tolist()) # [1.0, 2.0, 2.0, 3.0]Плотная нумерация рангов: без пропусков после равенства
Метод 'dense' особенно полезен, когда нужна нумерация рангов без пропусков. При использовании 'min' две записи, занявшие 2-е место, приводят к тому, что следующий ранг будет равен 4 (ранг 3 пропускается). При использовании 'dense' следующий ранг всегда равен 3, поэтому последовательность остаётся непрерывной. Плотная нумерация рангов используется по стандарту в оконной функции SQL DENSE_RANK() и часто применяется в таблицах лидеров.
import pandas as pd
df = pd.DataFrame({
'name': ['A', 'B', 'C', 'D', 'E'],
'score': [100, 80, 80, 60, 60]
})
df['dense_rank'] = df['score'].rank(method='dense', ascending=False).astype(int)
print(df)
# name score dense_rank
# 0 A 100 1
# 1 B 80 2
# 2 C 80 2 <- same score, same rank
# 3 D 60 3 <- next rank is 3, not 4
# 4 E 60 3Процентильный ранг с pct=True
Установка pct=True в rank() нормализует ранги к диапазону [0, 1], формируя процентильный ранг. Значение с процентильным рангом 0.8 выше 80% значений в столбце. Это применяется в финансах (процентильная оценка результатов), при выставлении оценок (процентили баллов) и для обнаружения выбросов.
import pandas as pd
df = pd.DataFrame({'score': [50, 70, 80, 90, 100]})
df['percentile'] = df['score'].rank(pct=True)
print(df)
# score percentile
# 0 50 0.2
# 1 70 0.4
# 2 80 0.6
# 3 90 0.8
# 4 100 1.0Ранжирование внутри групп
Чтобы независимо вычислять ранги внутри каждой группы (например, ранг зарплаты в каждом отделе), объедините groupby() и rank(). Используйте groupby().rank(): она применяет функцию ранжирования к каждой группе и возвращает Series, согласованный с исходным индексом DataFrame — это идеально подходит для добавления столбца «ранг внутри группы».
import pandas as pd
df = pd.DataFrame({
'dept': ['Eng', 'Eng', 'HR', 'HR', 'Eng'],
'name': ['Alice', 'Bob', 'Carol', 'Dave', 'Eve'],
'salary': [90000, 70000, 55000, 65000, 80000]
})
df['dept_rank'] = df.groupby('dept')['salary'].rank(
method='dense', ascending=False
).astype(int)
print(df.sort_values(['dept', 'dept_rank']))
# dept name salary dept_rank
# 0 Eng Alice 90000 1
# 4 Eng Eve 80000 2
# 1 Eng Bob 70000 3
# 3 HR Dave 65000 1
# 2 HR Carol 55000 2pd.cut() для интервалов одинаковой ширины
pd.cut(series, bins) делит непрерывный числовой столбец на интервалы одинаковой ширины (интервалы) и относит каждое значение к своему интервалу. Это преобразует непрерывную переменную в категориальную и полезно для гистограмм, возрастных групп, диапазонов дохода и любых задач дискретизации. В результате получается категориальный Series с метками интервалов.
import pandas as pd
df = pd.DataFrame({'age': [5, 15, 25, 35, 45, 55, 65, 75]})
df['age_group'] = pd.cut(df['age'], bins=[0, 18, 35, 60, 100],
labels=['Child', 'Young Adult', 'Middle Age', 'Senior'])
print(df)
# age age_group
# 0 5 Child
# 1 15 Child
# 2 25 Young Adult
# 3 35 Young Adult
# 4 45 Middle Age
# 5 55 Middle Age
# 6 65 Senior
# 7 75 Seniorpd.qcut() для интервалов с одинаковой частотой
pd.qcut(series, q) делит значения на интервалы, основанные на квантилях, при этом каждый интервал содержит примерно одинаковое число наблюдений. В отличие от pd.cut() (одинаковая ширина), pd.qcut() создаёт группы одинакового размера — это полезно для сегментации по процентилям, например при разбиении на децили, квинтили или квартили.
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({'score': np.random.randint(40, 100, 20)})
# Split into 4 equal-frequency quartiles
df['quartile'] = pd.qcut(df['score'], q=4, labels=['Q1', 'Q2', 'Q3', 'Q4'])
print(df['quartile'].value_counts().sort_index())
# Q1 5
# Q2 5
# Q3 5
# Q4 5cut() и qcut() — ключевые различия
Используйте pd.cut(), когда интервалы имеют естественный смысл в предметной области (например, возрастные диапазоны 0–18, 18–35, 35–60), то есть ширина интервалов важна с точки зрения смысла. Используйте pd.qcut(), когда нужны группы одинакового размера независимо от положения границ — например, чтобы разделить клиентов на верхний и нижний квартили. При асимметричном распределении cut() создаёт очень неравные группы, а qcut() — группы одинакового размера.
import pandas as pd
import numpy as np
np.random.seed(0)
# Skewed distribution: most values near 0
skewed = pd.Series(np.random.exponential(scale=5, size=100).round())
# cut with equal width: many empty or tiny upper bins
cut_counts = pd.cut(skewed, bins=4).value_counts().sort_index()
print('cut():', cut_counts.values)
# qcut with equal frequency: always 25 per group
qcut_counts = pd.qcut(skewed, q=4).value_counts().sort_index()
print('qcut():', qcut_counts.values)Добавление номера ранга в качестве столбца
Удобный шаблон для создания таблицы с ранжированными результатами таков: отсортировать данные по убыванию, сбросить индекс до начинающегося с 0, прибавить 1 для понятной человеку нумерации с 1 и вывести ранг рядом с исходными данными. В результате получается готовая к представлению таблица лидеров без пропусков и с аккуратными номерами рангов.
import pandas as pd
df = pd.DataFrame({
'team': ['Falcons', 'Eagles', 'Hawks', 'Owls'],
'wins': [12, 9, 12, 7]
})
leaderboard = (
df
.sort_values('wins', ascending=False)
.reset_index(drop=True)
)
leaderboard.index = leaderboard.index + 1
leaderboard.index.name = 'place'
print(leaderboard)Ранг как признак для машинного обучения
Признаки, преобразованные в ранги, полезны в машинном обучении, поскольку они устойчивы к выбросам: очень большое или очень маленькое значение получает ранг, близкий к одному из крайних, вместо того чтобы искажать распределение признака. Ранговое преобразование иногда используют на этапе предварительной обработки перед моделями на основе деревьев или когда числовой масштаб не имеет значения, но важен относительный порядок.
import pandas as pd
import numpy as np
df = pd.DataFrame({
'income': [30000, 50000, 70000, 1_000_000] # outlier at 1M
})
# Add rank as a feature
df['income_rank'] = df['income'].rank(pct=True)
print(df)
# income income_rank
# 0 30000 0.25
# 1 50000 0.50
# 2 70000 0.75
# 3 1000000 1.00
# The outlier has rank 1.0 — extreme but not disproportionateБыстрая проверка
Проверьте, насколько хорошо Вы понимаете ранжирование значений в Pandas.
Итоги урока
В этом уроке Вы узнали: rank() присваивает значениям порядковые позиции, method='dense' предотвращает пропуски после одинаковых рангов, pct=True возвращает процентильные ранги в диапазоне [0,1], а groupby().rank() вычисляет ранги внутри групп. Используйте pd.cut() для интервалов одинаковой ширины, а pd.qcut() — для интервалов с одинаковой частотой при дискретизации непрерывных переменных. Далее Вы научитесь задавать и сбрасывать индекс DataFrame.
Изучай Python с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 30
- Уроки
- 120
Часто задаваемые вопросы
Урок «Ранжирование значений» бесплатный?
Да — полный текст урока «Ранжирование значений» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Pandas & NumPy Academy, подпишись на CoddyKit PRO. Курс Pandas & NumPy Academy содержит 4 уроков всего.
Чему я научусь в уроке «Ранжирование значений»?
Присваивайте значениям столбца ранги с помощью rank(), выбирайте способы разрешения одинаковых значений и создавайте интервалы процентилей с помощью pd.cut(). Ты практикуешь Pandas & NumPy Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Pandas & NumPy Academy?
Предыдущий опыт не требуется. Pandas & NumPy Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Ранжирование значений»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Pandas & NumPy Academy?
Да. Каждый урок Pandas & NumPy Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Сортировка по значениям столбцов
- Сортировка по индексу
- Ранжирование значений
- Установка и сброс индекса