Skip to content

pandas sort_values

Sort rows by the values in one or more columns.

sort_values is the method that turns a correct answer into a readable one. A grouped total sorted alphabetically tells you almost nothing; the same total sorted descending tells you who the biggest players are at a glance.

Official documentation: DataFrame.sort_values

The forms worth knowing

# One column, largest first
df.sort_values('Capacity (MW)', ascending=False)

# Several columns -- earlier ones win ties
df.sort_values(['Country', 'Capacity (MW)'])

# A different direction per column
df.sort_values(['Country', 'Capacity (MW)'], ascending=[True, False])

# Missing values first instead of last
df.sort_values('mag', na_position='first')

# Sort a Series (e.g. the result of groupby or value_counts)
df.groupby('Country')['Capacity (MW)'].sum().sort_values(ascending=False)

Note that sort_values takes column names as strings, not pd.col expressions — it wants to know which column, not a computed value.

A worked example, on real data

The Global Coal Plant Tracker lists every coal-fired generating unit on earth, one row per unit. Bamboo Weekly #64 used this dataset.

Suppose we want each country's units listed together, biggest first within each country. That is a two-key sort with different directions:

import pandas as pd

url = ('https://www.bambooweekly.com/content/files/wp-content/uploads/2024/02/'
       'global-coal-plant-tracker-january-2024.xlsx')

(
    pd.read_excel(url, sheet_name='Units',
                  usecols=['Country', 'Status', 'Capacity (MW)'])
    .sort_values(['Country', 'Capacity (MW)'], ascending=[True, False])
    .head(4)
)

Which gives:

  Country  Capacity (MW)       Status
  Albania          800.0    cancelled
Argentina          375.0    operating
Argentina          120.0    operating
Argentina          120.0 construction

Countries ascending, capacity descending inside each — the ascending=[True, False] list is what makes those two directions possible in a single call.

Three mistakes people make

Forgetting that it returns a new frame. df.sort_values('x') does not reorder df; it hands back a sorted copy. Either chain onto it or keep the result. (inplace=True exists but works against method chaining, and its behavior changed in Pandas 3 — prefer the returned value.)

Sorting a grouped result and losing the sort. groupby returns results ordered by the group key. If you sort and then group, the grouping re-sorts by key and your work is gone. Sort after aggregating, not before.

Assuming the index comes along in a useful order. After sorting, the index is shuffled — row 0 is no longer the first row of the original. If positional access matters afterwards, chain .reset_index(drop=True).

Watch it

How to sort in Pandas covers this in a few minutes.

Practice it

Work through a sort_values exercise, with instant feedback and no signup required: practice.lernerpython.com/bamboo-weekly/sort-values/

Go deeper

Bamboo Weekly is the practice. If you want the structured version — full courses with downloadable Jupyter notebooks, plus live Pandas office hours when you get stuck — that is LernerPython+Data. A paid Bamboo Weekly subscription is included with it.

See it on real data

Below are the 108 Bamboo Weekly exercises that use sort_values on real-world data — try each one, then study the worked solution.

Part of the Pandas Methods Index. See also practice by skill.