100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Python

Sorting and Ranking

How to order DataFrames and Series with sort_values and sort_index, and how to assign competitive ranks to values with the rank method and its tie-breaking strategies.

Data TransformationBeginner8 min readJul 8, 2026
Analogies

Sorting and Ranking

Sorting rearranges rows so that a chosen column (or the index) is in ascending or descending order, while ranking assigns each value a numeric position relative to the others without necessarily reordering the data itself. Pandas exposes sort_values and sort_index for the former, and rank for the latter. These operations are foundational: leaderboard tables, top-N reports, percentile calculations, and time-ordered analysis all depend on getting sorting and ranking semantics right — especially around how ties and missing values are handled.

🏏

Cricket analogy: Sorting rearranges a season's scorecard so Virat Kohli's highest score sits at the top, while ranking assigns him a position (like 3rd-highest run-scorer) without reordering the underlying match list, which matters for building an accurate leaderboard.

sort_values: ordering by column content

DataFrame.sort_values(by=...) reorders rows based on the values in one or more columns. Passing a list to by sorts hierarchically — the first column breaks the biggest ties, subsequent columns break ties within those. The ascending parameter can be a single bool or a list matching the by list, letting you mix ascending and descending order across columns in a single call. By default, NaN values are pushed to the end of the sort regardless of direction, which is controlled by the na_position parameter ('last' by default, or 'first').

🏏

Cricket analogy: sort_values(by=['team','runs'], ascending=[True, False]) groups a scorecard by team alphabetically first, then ranks each team's batters highest-runs-first within that group, and na_position='last' pushes any player missing a runs entry to the bottom regardless of sort direction.

python
import pandas as pd
import numpy as np

students = pd.DataFrame({
    'name': ['Ravi', 'Meera', 'Anil', 'Divya', 'Kiran'],
    'grade': [9, 10, 9, 8, np.nan],
    'score': [88, 95, 91, 76, 60]
})

# Sort by grade descending, then score descending within each grade
ranked = students.sort_values(by=['grade', 'score'], ascending=[False, False], na_position='last')
print(ranked)
#     name  grade  score
# 1  Meera   10.0     95
# 2   Anil    9.0     91
# 0   Ravi    9.0     88
# 3  Divya    8.0     76
# 4  Kiran    NaN     60

sort_index: ordering by the index

sort_index reorders rows (or columns, with axis=1) by the index labels rather than by cell values. This is especially useful after operations like groupby or merge that can leave the index in a non-obvious order, or after filtering that leaves gaps in a RangeIndex. For a MultiIndex, sort_index accepts a level argument to sort by a specific index level, and can sort remaining levels lexicographically by default.

🏏

Cricket analogy: sort_index() after a groupby that produced runs-per-team leaves teams out of alphabetical order; calling sort_index() restores it, and for a MultiIndex of team-then-player, passing level='team' sorts only by team while player order within remains lexicographic.

rank: assigning positions and handling ties

Series.rank() (and DataFrame.rank() applied per column) returns a same-shaped object where each value is replaced by its rank among the other values, with 1 being the lowest by default. The method parameter controls tie-breaking: 'average' (default) gives tied values the mean of the ranks they would occupy; 'min' gives all tied values the lowest of those ranks; 'max' gives the highest; 'first' breaks ties by order of appearance; and 'dense' behaves like 'min' but doesn't leave gaps in the rank sequence. Choosing the right method matters for leaderboards (where 'min' avoids skipping a rank after a tie) versus dense classification schemes.

🏏

Cricket analogy: Series.rank() on a season's run totals with method='min' means two batters tied for 2nd both get rank 2, avoiding a skipped rank 3, which matters for an accurate Orange Cap leaderboard, while 'dense' would rank the next distinct total as 3 without a gap.

python
import pandas as pd

scores = pd.Series([88, 95, 88, 76], index=['Ravi', 'Meera', 'Anil', 'Divya'])

print(scores.rank(ascending=False, method='min'))
# Meera    1.0
# Ravi     2.0
# Anil     2.0
# Divya    4.0   <- 'min' skips rank 3 because two values tied for 2

print(scores.rank(ascending=False, method='dense'))
# Meera    1.0
# Ravi     2.0
# Anil     2.0
# Divya    3.0   <- 'dense' does not skip a rank number

rank(pct=True) converts ranks into percentiles between 0 and 1, which is a quick way to compute percentile scores for a column without manually dividing by the count.

sort_values does not sort in place by default — it returns a new DataFrame. Forgetting to reassign (df = df.sort_values(...)) or pass inplace=True is a very common bug that leaves the original order untouched.

  • sort_values orders rows by one or more column values; sort_index orders by the index labels.
  • Passing a list to by/ascending in sort_values enables multi-column, mixed-direction sorting.
  • NaN values sort to the end by default in sort_values, controllable via na_position.
  • rank() assigns numeric positions to values, with tie-breaking controlled by the method parameter.
  • method='min' vs 'dense' differ in whether tied ranks leave gaps in the subsequent rank numbers.
  • sort_values and sort_index return new objects by default; use inplace=True or reassignment to persist the change.

Practice what you learned

Was this page helpful?

Topics covered

#Python#PandasNumPyStudyNotes#DataScience#SortingAndRanking#Sorting#Ranking#Sort#Values#Algorithms#StudyNotes#SkillVeris