Which product sells most? Who are your top ten customers? What's the slowest step in the pipeline? Every one of these is a sorting question — and pandas answers them in a single line. Once you can order and rank data on demand, 'what's the best/worst?' stops being a chore and becomes a reflex.
What you'll learn
What
Sorting reorders rows by the values in one or more columns. Ranking assigns each row a position number within a column. Together they turn an unordered table into a leaderboard, a priority list, or a top-N shortlist.
Why
Decisions are made at the extremes — the best customers, the worst-performing regions, the highest-risk transactions. Sorting surfaces those extremes instantly, and ranking lets you compare positions even when the raw values are hard to interpret.
Where it's used
Building leaderboards, ranking search results, prioritising a backlog, finding outliers at the top and bottom of a distribution, and preparing ordered data for time-series or window operations.
Where this runs in production
Videos are ranked by a score combining views, watch-time, and recency; sort_values on that score, descending, produces the trending shelf you see on the homepage.
Merchandising teams call nlargest(20, 'units_sold') to pull the top twenty products per category in milliseconds, far faster than sorting the entire multi-million-row catalogue.
Engineers rank drivers by lap time with rank(method='min') so tied laps share a position, matching how race classifications actually work.
import pandas as pd
df = pd.DataFrame({'name':['Amara','Jamal','Priya'], 'sales':[120, 300, 200]})
top = df.sort_values(by='sales', ascending=False)
print(top['name'].tolist()) # highest sales firstascending=False puts the biggest sales at the top. The result is a new DataFrame; the original df is untouched unless you reassign or pass inplace=True.
df.sort_values(by=['region', 'sales'],
ascending=[True, False])This orders regions alphabetically (ascending), and within each region puts the highest sales first (descending). The ascending list lines up position-by-position with the by list.
To get the top 10, df.nlargest(10, 'sales') is both clearer and faster than df.sort_values('sales', ascending=False).head(10) — it finds the top 10 without fully sorting every row. nsmallest does the same for the bottom.
Two runners cross the line together in second place. In a real race (method='min') they both get rank 2 and the next runner is 4 — positions are skipped. In dense ranking (method='dense') they get 2 and the next is 3 — no gaps, like ranking distinct tiers. The default 'average' gives both 2.5, the mean of the positions they occupy. Pick the one that matches how your domain counts ties.
After sort_values, the index is shuffled to match the new order; call reset_index(drop=True) if you need clean 0-based positions. Also, by default missing values are placed last regardless of sort direction (na_position='last'); pass na_position='first' to change that. Don't assume the first row is the smallest if NaNs are present.
Click each tool to see what it returns and when to choose it.
Select a type to see its full definition, operations, and data science usage.
Order salespeople from highest to lowest sales.
Three salespeople with unordered sales figures.
Your task
A streaming service wants a quick leaderboard from its shows table. Complete the sorting and ranking tasks.
['Bravo', 'Cosmo', 'Echo'] [4.0, 1.0, 1.0, 5.0, 3.0] ['Bravo', 'Delta', 'Cosmo', 'Echo', 'Alpha']
Write your solution in the editor on the right, then hit Run.
Which call sorts a DataFrame so the largest 'score' is first?
What's the advantage of df.nlargest(10, 'x') over df.sort_values('x', ascending=False).head(10)?
Using rank(method='min') on scores [90, 90, 75], what ranks do the two 90s and the 75 receive (ascending, default direction)?
Why, and what's the fix?
Given the DataFrame below, print the name of the region with the second-highest total sales. df = pd.DataFrame({'region':['N','S','E','W'], 'sales':[400, 900, 900, 250]}) Note: N and... actually S and E tie at 900. Use nlargest, which keeps ties in original order, so the second row of the top 2 is E.
By default, where does sort_values place NaN values?
How do you sort a DataFrame by multiple columns with different directions?
I pass a list of columns to sort_values via by, and a matching list of booleans to ascending. pandas sorts by the first column, uses the second to break ties, and so on down the list, with each column taking its own direction from the ascending list position-for-position. For example, sort_values(by=['region', 'sales'], ascending=[True, False]) orders regions alphabetically and, within each region, puts the highest sales first. If I need clean positional labels afterward I chain reset_index(drop=True), because sorting keeps the original index.
What's the difference between the tie-handling methods in rank(), and when would you use each?
rank() offers several methods that differ only in how tied values are treated. 'min' gives every tied value the lowest position in the group and skips the next positions — that's competition ranking, what sports use, where two firsts mean no second. 'max' gives them the highest position in the group instead. 'dense' also shares the rank for ties but doesn't skip, so ranks are consecutive integers — good when I'm ranking distinct tiers and don't want gaps. 'first' breaks ties by order of appearance, giving strictly unique ranks. The default 'average' assigns the mean of the positions the ties span, which is the right choice for statistical work like computing rank correlations. I pick based on the domain: leaderboards use 'min', tiering uses 'dense', and Spearman-style statistics use 'average'.
How would you efficiently get the top-K rows from a very large DataFrame, and why not just sort?
For top-K I use nlargest(k, col) rather than sorting the whole frame. A full sort is O(n log n) over every row, but I only need the K largest, and nlargest uses a selection algorithm that effectively maintains a bounded heap of the current top K in roughly O(n log k) — a big win when n is millions and k is small, and it reads more clearly as intent. It also handles the tie and NaN semantics sensibly out of the box. If the data is truly huge and lives out of memory, I'd push the ordering down to the source — a SQL ORDER BY ... LIMIT, or a partitioned top-K in a distributed engine — so I never materialise the full sorted set. Sorting first is fine for small frames or when I genuinely need the entire ordering, but for 'just the top 20' nlargest is the right tool.
Common Mistakes to Avoid
1) Expecting .loc[0] to be the first row after sorting — sort_values keeps original labels; use .iloc[0] or reset_index(drop=True). 2) Forgetting ascending=False for leaderboards — the default is smallest-first. 3) Assuming NaNs sort to the top — they go last by default (na_position='last'). 4) Using the wrong rank tie method — 'min' for competitions, 'dense' for tiers, 'average' for statistics; the default 'average' produces fractional ranks that surprise people. 5) Sorting the whole frame just to take the top 10 — nlargest is faster and clearer. 6) Mismatching the lengths of the by and ascending lists in a multi-column sort.
Ask the AI Tutor
Try these prompts in the AI Tutor panel: • 'ELI5: what's the difference between sorting and ranking?' • 'Show me every rank() tie method on the same tied data.' • 'Quiz me on where NaNs land when I sort.' • 'Explain why nlargest can beat sort().head().' • 'Interview mode: ask me to build a competition leaderboard with ties.'
Glossary
sort_values(by, ascending) — reorder rows by one or more columns. sort_index() — reorder rows by their index labels. nlargest / nsmallest(n, col) — return the top/bottom N rows by a column without a full sort. rank(method, ascending) — assign each row a position within a column. method='min' — competition ranking (ties share the lowest position, gaps after). method='dense' — consecutive ranks with no gaps. method='average' — the default; ties get the mean position. na_position — where NaNs are placed when sorting ('last' by default). reset_index(drop=True) — renumber rows 0,1,2 after reordering.
Recommended Resources
• Docs: the pandas 'Sorting' section of the basics guide, plus the rank() API reference for every tie method. • Read: the nlargest/nsmallest reference to see how ties (keep='first'/'last'/'all') are handled. • Practice: take a scores table with deliberate ties and produce three leaderboards using rank methods 'min', 'dense', and 'average' — compare how the tied rows differ. • Next in DSM: you've mastered the pandas core — Data Cleaning starts next. First up is Common Data Quality Issues, a field guide to the messes real datasets arrive in and a workflow to audit them.
Recap
✓ sort_values(by, ascending) reorders rows; pass lists to sort by several columns with per-column directions. ✓ Sorting keeps the original index — reset_index(drop=True) for clean 0-based positions. ✓ nlargest / nsmallest pull the top/bottom N faster and clearer than sort-then-head. ✓ rank() assigns positions; the method argument sets tie handling — 'min', 'dense', 'average', 'max', 'first'. ✓ ascending=False on sort or rank makes the largest value first / rank 1. ✓ By default NaNs sort last, regardless of direction. Next up: Common Data Quality Issues. You can order and rank clean data — but first you have to make it clean. The Data Cleaning module opens with a field guide to the problems real datasets arrive with, and a workflow to catch them.
Run your code to see the output here.