Pandas has two sort functions that get confused constantly. Sort_index reorders rows and columns based on their labels. Sort_values reorders rows based on the data inside the cells. They look similar. They are not interchangeable—using the wrong one is a common source of puzzling errors.
Key facts
- Sort_index sorts by DataFrame labels, not cell values
- Default behaviour sorts rows in ascending order using quicksort
- Pass axis=1 to sort columns instead of rows
- Use ascending=False to reverse the sort order
- Use na_position='first' to place NaN labels at the top
How sort_index actually works
You have a DataFrame loaded from a CSV. The rows have integer index labels like 429, 1543, 1441, in whatever order the CSV produced them. Calling df.sort_index() rearranges the rows so the labels run in ascending order: 300, 393, 429, and so on.
The data inside the rows moves along. The row that was at label 429 is still the same row, just in a new position. Nothing about the cell values changed.
That is the key distinction. Sort_index reorders. It does not compute anything new.
Sorting columns alphabetically
Pass axis=1 to sort columns by their labels instead of rows. If your columns are named M, L, T, G, X, Z, calling df.sort_index(axis=1) reorders them to G, L, M, T, X, Z. Strings sort alphabetically by default.
Cleaning up a DataFrame with columns in a random order is a one-liner with sort_index.
Handling NaN labels
By default, rows with NaN labels end up at the bottom of the sorted result. Pass na_position='first' to bring them to the top instead.
In time-series data, NaN labels often represent missing dates. You usually want them at the end so the valid range is contiguous. But when doing a quick check for missing data, putting them at the top makes them easier to spot.
sort_index vs sort_values: When to use each
The mental model that helps: sort_index is for the scaffolding, sort_values is for the content.
| Task | Use this |
|---|---|
| Reorder rows by their label | sort_index() |
| Reorder rows by a column's values | sort_values(by="column") |
| Reorder columns alphabetically | sort_index(axis=1) |
| Control NaN placement | na_position parameter |
In practice, sort_values gets called far more often. Most data analysis cares about ranking observations, not labels. Sort_index is the specialist tool: time-series alignment, column reordering, clean output for reports.
A common pattern is to combine them. Sort by index first to get clean chronological order, then sort by values within groups for ranking. Pandas makes both work in sequence without breaking the other.
Worked example: cleaning up a sensor log
Imagine you have a DataFrame indexed by timestamps. The timestamps are out of order because the sensor had a clock drift. You want to fix the order without recomputing anything.
Call df.sort_index(). The rows rearrange so timestamps run chronologically. The readings stay attached to their original timestamps. You now have a clean time series.
For a report, you also want the columns in a logical order. If the CSV gave you columns in a different order, df.sort_index(axis=1) alphabetises them. Use explicit column selection with df[['timestamp', 'sensor_id', 'temperature', 'humidity', 'battery']] instead for precise control over column ordering.
What to watch next
Pass inplace=True to modify the DataFrame in place rather than returning a copy. Most production code reassigns the result explicitly to avoid mutating the original unexpectedly.
Key takeaways
- Sort_index works on labels, sort_values works on cell data
- Use axis=1 to sort columns; default is rows
- Pass na_position to control where NaN labels land
- Pass inplace=True to modify the DataFrame directly
- Combine sort_index and sort_values in sequence for powerful pipelines
Frequently asked questions
What is the difference between sort_index and sort_values?
Sort_index sorts by row and column labels. Sort_values sorts by the actual data in cells and requires specifying a column with the by parameter.
Can I sort in descending order?
Yes. Pass ascending=False to either function.
Does sort_index modify the original DataFrame?
Not by default. It returns a new DataFrame. Pass inplace=True to modify in place, but be aware this mutates the original.
How do I sort columns instead of rows?
Pass axis=1 to sort by column labels instead of row labels.