Skip to main content
MahiDev — Learn. Build. Become AI-ready.

Lesson 14

Sorting Data

Order a Series or a DataFrame by its values or by its index, sort on several columns at once, and grab the top rows with nlargest.

Intermediate25 min
Sorting Data hero Module 24 Lesson 14Sorting Data hero Module 24 Lesson 14

sort_values orders by what is in the cells and sort_index orders by the labels. Both return a new object and both carry the index along, so a row keeps its label wherever it lands.

A table before and after sorting by score, with labels following the rowsA table before and after sorting by score, with labels following the rows

Sort a Series

sort_values on a Series orders the values and drags the labels with them. sort_index puts the labels back in order, which is how you undo a value sort.

python
import pandas as pd

sales = pd.Series([120, 85, 140, 95], index=["Mon", "Tue", "Wed", "Thu"])
print(sales.sort_values())
print(sales.sort_values(ascending=False))
print(sales.sort_index())

Output:

text
Tue     85
Thu     95
Mon    120
Wed    140
dtype: int64
Wed    140
Mon    120
Thu     95
Tue     85
dtype: int64
Mon    120
Thu     95
Tue     85
Wed    140
dtype: int64

Sort a DataFrame

Name the column to sort by. ascending=False gives largest first. The index comes along, so reset_index(drop=True) is what you want if the old numbers only cause confusion.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
print(learners.sort_values("score", ascending=False)[["name", "score"]])
print(learners.sort_values("hours").reset_index(drop=True)[["name", "hours"]])

Output:

text
     name  score
2   Casey     91
0   Avery     88
4  Morgan     82
5   Quinn     79
1  Jordan     74
3   Riley     65
     name  hours
0   Riley     24
1  Jordan     31
2   Quinn     38
3   Avery     42
4  Morgan     47
5   Casey     55

Several columns at once

A list of names sorts by the first, then breaks ties with the second. ascending can be a list too, one value per column, so you can sort a group ascending and its scores descending.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
print(learners.sort_values(["track", "score"])[["track", "name", "score"]])
print(
    learners.sort_values(["track", "score"], ascending=[True, False])
    [["track", "name", "score"]]
)

Output:

text
    track    name  score
1   NumPy  Jordan     74
4   NumPy  Morgan     82
0  Python   Avery     88
2  Python   Casey     91
3  pandas   Riley     65
5  pandas   Quinn     79
    track    name  score
4   NumPy  Morgan     82
1   NumPy  Jordan     74
2  Python   Casey     91
0  Python   Avery     88
5  pandas   Quinn     79
3  pandas   Riley     65

Sort by label

sort_index() orders the rows by their labels, and axis=1 orders the columns by name instead, which is handy when two tables should line up for comparison.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
tagged = learners.set_index("name")
print(tagged.sort_index()[["track", "score"]])
print(tagged.sort_index(axis=1).head(2))

Output:

text
         track  score
name                 
Avery   Python     88
Casey   Python     91
Jordan   NumPy     74
Morgan   NumPy     82
Quinn   pandas     79
Riley   pandas     65
             city  hours  score   track
name                                   
Avery   Northgate     42     88  Python
Jordan   Eastport     31     74   NumPy

Just the top few

nlargest and nsmallest sort and cut in one step, which is both shorter and quicker than sorting a big table to look at five rows. Missing values sort to the end by default.

python
import pandas as pd

learners = pd.DataFrame({
    "name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
    "track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
    "city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
    "hours": [42, 31, 55, 24, 47, 38],
    "score": [88, 74, 91, 65, 82, 79],
})
print(learners.nlargest(3, "score")[["name", "score"]])
print(learners.nsmallest(2, "hours")[["name", "hours"]])
print(learners["score"].rank(ascending=False).astype(int).tolist())

Output:

text
     name  score
2   Casey     91
0   Avery     88
4  Morgan     82
     name  hours
3   Riley     24
1  Jordan     31
[2, 5, 1, 6, 3, 4]

rank numbers the values without moving any rows.

Key takeaways

  • sort_values orders by cell values and sort_index by labels

  • A list of columns sorts by the first and breaks ties with the next

  • ascending can be a list, one value per sort column

  • nlargest and nsmallest beat sorting a whole table for a top-few view

  • Next: Column Types and astype

  • Previous: Removing Columns and Rows

Loading playground…

Check your understanding

Sorting Data Quiz

What does sort_values order by?

1 / 10