Reversing the order of rows in a DataFrame is a common operation in data analysis. You might need to flip your data to display the most recent entries first, reverse a time series for backward analysis, or simply reorder records for presentation purposes. Pandas provides several straightforward methods to achieve this.
In this guide, you'll learn multiple ways to reverse rows in a Pandas DataFrame, understand how each method handles the index, and choose the right approach for your use case.
Creating a Sample DataFrame
Let's start with a simple DataFrame to demonstrate all the methods:
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
print(df)Output:
Name Income Expenses Profit
0 Alice 150000 10000 5000
1 Bob 130000 11000 2000
2 Charlie 110000 7000 4000
3 Diana 95000 50000 6000Method 1: Using iloc[::-1] (Recommended)
The simplest and most Pythonic way to reverse rows is using iloc with Python's slice notation [::-1]:
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
reversed_df = df.iloc[::-1]
print(reversed_df)Output:
Name Income Expenses Profit
3 Diana 95000 50000 6000
2 Charlie 110000 7000 4000
1 Bob 130000 11000 2000
0 Alice 150000 10000 5000Notice that the original index is preserved - the rows are reversed but their index labels (3, 2, 1, 0) stay with their respective data.
Method 2: Using loc[::-1]
The loc accessor works similarly to iloc when used with slice notation:
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
reversed_df = df.loc[::-1]
print(reversed_df)Output:
Name Income Expenses Profit
3 Diana 95000 50000 6000
2 Charlie 110000 7000 4000
1 Bob 130000 11000 2000
0 Alice 150000 10000 5000The result is identical to iloc[::-1]. The difference between loc and iloc matters more when selecting specific rows or columns:
ilocuses integer positions (0, 1, 2, ...).locuses index labels (which may be strings, dates, etc.).
For simple row reversal with a default integer index, both produce the same result.
Method 3: Using Direct Slicing df[::-1]
You can also reverse rows by slicing the DataFrame directly without loc or iloc:
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
reversed_df = df[::-1]
print(reversed_df)Output:
Name Income Expenses Profit
3 Diana 95000 50000 6000
2 Charlie 110000 7000 4000
1 Bob 130000 11000 2000
0 Alice 150000 10000 5000This is the most concise syntax, though iloc[::-1] is generally preferred for clarity.
Method 4: Reversing and Resetting the Index
After reversing, the index is in descending order (3, 2, 1, 0). If you want a clean, sequential index starting from 0, use reset_index():
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
reversed_df = df.iloc[::-1].reset_index(drop=True)
print(reversed_df)Output:
Name Income Expenses Profit
0 Diana 95000 50000 6000
1 Charlie 110000 7000 4000
2 Bob 130000 11000 2000
3 Alice 150000 10000 5000Method 5: Using reindex()
The reindex() method lets you rearrange rows according to a new index order:
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
reversed_df = df.reindex(index=df.index[::-1])
print(reversed_df)Output:
Name Income Expenses Profit
3 Diana 95000 50000 6000
2 Charlie 110000 7000 4000
1 Bob 130000 11000 2000
0 Alice 150000 10000 5000This method is more verbose but useful when you need to reorder rows based on a custom index sequence, not just a simple reversal.
Method 6: Using sort_index(ascending=False)
If your DataFrame has a meaningful index (like dates or sequential IDs), you can reverse it by sorting the index in descending order:
import pandas as pd
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Income': [150000, 130000, 110000, 95000],
'Expenses': [10000, 11000, 7000, 50000],
'Profit': [5000, 2000, 4000, 6000]
}
df = pd.DataFrame(data)
reversed_df = df.sort_index(ascending=False)
print(reversed_df)Output:
Name Income Expenses Profit
3 Diana 95000 50000 6000
2 Charlie 110000 7000 4000
1 Bob 130000 11000 2000
0 Alice 150000 10000 5000This is particularly useful with DatetimeIndex DataFrames:
import pandas as pd
dates_df = pd.DataFrame({
'Sales': [100, 200, 150, 300]
}, index=pd.date_range('2025-01-01', periods=4))
print("Original:")
print(dates_df)
print("\nReversed (most recent first):")
print(dates_df.sort_index(ascending=False))Output:
Original:
Sales
2025-01-01 100
2025-01-02 200
2025-01-03 150
2025-01-04 300
Reversed (most recent first):
Sales
2025-01-04 300
2025-01-03 150
2025-01-02 200
2025-01-01 100Reversing Rows In Place
All the methods above return a new DataFrame without modifying the original. If you want to reverse the original DataFrame in place, reassign it:
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],
'Score': [85, 92, 78]
})
df = df.iloc[::-1].reset_index(drop=True)
print(df)Output:
Name Score
0 Charlie 78
1 Bob 92
2 Alice 85Common Mistake: Forgetting to Reset the Index
A common issue is performing operations on a reversed DataFrame without resetting the index, which can lead to confusing behavior when accessing rows by position:
import pandas as pd
df = pd.DataFrame({'Value': [10, 20, 30, 40]})
reversed_df = df.iloc[::-1]
print("iloc[0]:", reversed_df.iloc[0]['Value']) # 40
print("loc[0]: ", reversed_df.loc[0]['Value']) # 10 (original row 0!)Output:
iloc[0]: 40
loc[0]: 10After reversing, iloc[0] gives the first row of the reversed order (value 40), while loc[0] still accesses index label 0 (value 10). Reset the index if this distinction causes confusion:
import pandas as pd
df = pd.DataFrame({'Value': [10, 20, 30, 40]})
reversed_df = df.iloc[::-1].reset_index(drop=True)
print("iloc[0]:", reversed_df.iloc[0]['Value']) # 40
print("loc[0]: ", reversed_df.loc[0]['Value']) # 40 (same row now)Output:
iloc[0]: 40
loc[0]: 40Comparison of Methods
| Method | Syntax | Preserves Original Index | Best For |
|---|---|---|---|
iloc[::-1] |
df.iloc[::-1] |
✅ | General-purpose reversal (recommended) |
loc[::-1] |
df.loc[::-1] |
✅ | Same as iloc for default index |
| Direct slicing | df[::-1] |
✅ | Most concise syntax |
reset_index() |
df.iloc[::-1].reset_index(drop=True) |
❌ (resets) | Clean sequential index needed |
reindex() |
df.reindex(index=df.index[::-1]) |
✅ | Custom index reordering |
sort_index() |
df.sort_index(ascending=False) |
✅ | Reversing by meaningful index (dates, IDs) |
Summary
To reverse rows in a Pandas DataFrame:
- Use
df.iloc[::-1]for the simplest, most readable approach - it works in all cases and is the recommended default. - Chain
.reset_index(drop=True)if you need a clean, sequential index starting from 0. - Use
sort_index(ascending=False)when working with meaningful indices like dates. - Be aware that after reversing,
ilocandlocbehave differently unless you reset the index.
All methods return a new DataFrame without modifying the original unless you explicitly reassign it.