Skip to main content

Python Pandas: How to Reset the Index of a Pandas DataFrame in Python

When you manipulate a Pandas DataFrame - by dropping rows, filtering, sorting, or slicing - the original index values are preserved. This can leave gaps in the index (e.g., 0, 3, 5, 7 instead of 0, 1, 2, 3), which can cause confusion and issues in downstream operations. The reset_index() method reassigns a clean, sequential integer index starting from 0.

In this guide, you will learn how to reset a DataFrame's index, control whether the old index is kept or discarded, and understand when resetting the index is necessary.

The Problem: Gaps in the Index After Dropping Rows

When you drop rows from a DataFrame, the index retains the original values:

import pandas as pd

df = pd.DataFrame({
'name': ['Jordan', 'Brady', 'James', 'Bryant',
'Rodriguez', 'Jeter', 'Williams', 'Ali',
'Phelps', 'Woods'],
'runs': [32292, 89214, 38652, 33643,
3115, 3465, 365, 56,
28, 82]
})

print("Original DataFrame:")
print(df)

Output:

Original DataFrame:
name runs
0 Jordan 32292
1 Brady 89214
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82

After dropping rows at index 0 and 1:

df = df.drop([0, 1])

print("After dropping rows 0 and 1:")
print(df)

Output:

After dropping rows 0 and 1:
name runs
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82

The index now starts at 2 instead of 0, and positions 0 and 1 are missing. This can cause issues with positional operations like iloc or when iterating with range(len(df)).

Resetting the Index With reset_index()

The reset_index() method creates a new sequential integer index:

import pandas as pd

df = pd.DataFrame({
'name': ['Jordan', 'Brady', 'James', 'Bryant',
'Rodriguez', 'Jeter', 'Williams', 'Ali',
'Phelps', 'Woods'],
'runs': [32292, 89214, 38652, 33643,
3115, 3465, 365, 56,
28, 82]
})

print("Original DataFrame:")
print(df)
print("\nAfter dropping rows 0 and 1:")
print(df)

# reset the index
df = df.reset_index(drop=True)

print("After resetting the index:")
print(df)

Output:

Original DataFrame:
name runs
0 Jordan 32292
1 Brady 89214
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82

After dropping rows 0 and 1:
name runs
0 Jordan 32292
1 Brady 89214
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82
After resetting the index:
name runs
0 Jordan 32292
1 Brady 89214
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82

The index is now clean and sequential: 0, 1, 2, ..., 7.

Key Parameter: drop

The drop parameter controls what happens to the old index:

drop=True - Discard the Old Index

The old index is removed completely:

df_reset = df.reset_index(drop=True)

This is the most common usage when the old index has no meaningful information.

drop=False (Default) - Keep the Old Index as a Column

The old index is preserved as a new column named index:

import pandas as pd 

df = pd.DataFrame({'value': [10, 20, 30]}, index=[5, 10, 15])

df_reset = df.reset_index() # drop=False by default
print(df_reset)

Output:

   index  value
0 5 10
1 10 20
2 15 30

The old index [5, 10, 15] is now a column called index.

When to keep the old index

Keep the old index (drop=False) when it contains meaningful data - for example, if the index represents dates, IDs, or category labels that you want to preserve as a regular column.

import pandas as pd

# Date index → keep as a column for analysis
df = pd.DataFrame({'price': [100, 105, 102]},
index=pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03']))

df_reset = df.reset_index() # Old index becomes a 'index' column (or the index name)
print(df_reset)

Output:

       index  price
0 2024-01-01 100
1 2024-01-02 105
2 2024-01-03 102

Resetting the Index In Place

By default, reset_index() returns a new DataFrame. To modify the original DataFrame directly, use inplace=True:

df.reset_index(drop=True, inplace=True)
warning

Using inplace=True modifies the original DataFrame and returns None. Do not assign the result to a variable:

# ❌ Wrong: result is None
df = df.reset_index(drop=True, inplace=True)
print(df) # None!

# ✅ Correct: either use inplace=True without assignment
df.reset_index(drop=True, inplace=True)

# ✅ Or assign without inplace
df = df.reset_index(drop=True)

Common Scenarios for Resetting the Index

After Filtering Rows

import pandas as pd

df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
'score': [85, 42, 91, 67, 73]
})

# Filter for scores above 70
passed = df[df['score'] > 70]
print("Before reset:")
print(passed)

passed = passed.reset_index(drop=True)
print("\nAfter reset:")
print(passed)

Output:

Before reset:
name score
0 Alice 85
2 Charlie 91
4 Eve 73

After reset:
name score
0 Alice 85
1 Charlie 91
2 Eve 73

After Sorting

import pandas as pd

df = pd.DataFrame({
'name': ['Charlie', 'Alice', 'Bob'],
'score': [91, 85, 42]
})

df_sorted = df.sort_values('name').reset_index(drop=True)
print(df_sorted)

Output:

      name  score
0 Alice 85
1 Bob 42
2 Charlie 91

After Concatenation

import pandas as pd

df1 = pd.DataFrame({'value': [1, 2, 3]})
df2 = pd.DataFrame({'value': [4, 5, 6]})

combined = pd.concat([df1, df2])
print("Before reset:")
print(combined)

combined = combined.reset_index(drop=True)
print("\nAfter reset:")
print(combined)

Output:

Before reset:
value
0 1
1 2
2 3
0 4
1 5
2 6

After reset:
value
0 1
1 2
2 3
3 4
4 5
5 6

Without resetting, the concatenated DataFrame has duplicate index values (two 0s, two 1s, two 2s), which can cause unexpected behavior with loc[].

After GroupBy Aggregation

import pandas as pd

df = pd.DataFrame({
'department': ['Sales', 'Sales', 'Engineering', 'Engineering'],
'salary': [50000, 60000, 80000, 90000]
})

avg_salary = df.groupby('department')['salary'].mean().reset_index()
print(avg_salary)

Output:

    department   salary
0 Engineering 85000.0
1 Sales 55000.0

Without reset_index(), the department name would be the index, not a column.

Complete Example

import pandas as pd

# Create DataFrame
df = pd.DataFrame({
'name': ['Jordan', 'Brady', 'James', 'Bryant',
'Rodriguez', 'Jeter', 'Williams', 'Ali',
'Phelps', 'Woods'],
'runs': [32292, 89214, 38652, 33643,
3115, 3465, 365, 56,
28, 82]
})

print("Original DataFrame:")
print(df)

# Drop rows at index 0 and 1
df = df.drop([0, 1])
print("\nAfter dropping rows 0 and 1:")
print(df)

# Reset the index
df = df.reset_index(drop=True)
print("\nAfter resetting the index:")
print(df)

Output:

Original DataFrame:
name runs
0 Jordan 32292
1 Brady 89214
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82

After dropping rows 0 and 1:
name runs
2 James 38652
3 Bryant 33643
4 Rodriguez 3115
5 Jeter 3465
6 Williams 365
7 Ali 56
8 Phelps 28
9 Woods 82

After resetting the index:
name runs
0 James 38652
1 Bryant 33643
2 Rodriguez 3115
3 Jeter 3465
4 Williams 365
5 Ali 56
6 Phelps 28
7 Woods 82

Quick Reference

ScenarioCode
Reset and discard old indexdf.reset_index(drop=True)
Reset and keep old index as columndf.reset_index()
Reset in placedf.reset_index(drop=True, inplace=True)
Reset after filteringdf[condition].reset_index(drop=True)
Reset after concatpd.concat([df1, df2]).reset_index(drop=True)
Reset after groupbydf.groupby('col').agg(...).reset_index()

Conclusion

The reset_index() method is essential for maintaining a clean, sequential index after operations that alter the DataFrame's structure, such as dropping rows, filtering, sorting, concatenating, or aggregating.

Use drop=True when the old index has no analytical value, and omit drop (or set it to False) when the old index contains meaningful data you want to preserve as a column.

Resetting the index prevents bugs caused by gaps, duplicates, or unexpected index values in downstream operations.