Renaming & Relabelling Columns and Index

Reviewed & published by Brayan K

Renaming is how you change the labels on a DataFrame — the column headers and index names — without touching the values stored underneath them.

Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

Learn to rename selected columns with a dict, relabel the index, replace the whole header list, clean names with .str methods, and tag columns with add_prefix and add_suffix.

What You'll Learn in This Lesson

1 Surgical Renaming — rename(columns={...})

rename() takes a dictionary that maps old label to new label. Only the labels you list change; everything else is left exactly as it was. That makes it the safe choice when a couple of column names came in wrong and the rest are fine. The same method relabels the row index via index={...}.

import pandas as pd

df = pd.DataFrame({"Name": ["Ann"], "Age in Yrs": [30]})

df = df.rename(columns={"Name": "name", "Age in Yrs": "age"})
# columns are now: name, age

df = df.rename(index={0: "first_row"})   # relabel a row in the index
import pandas as pd

df = pd.DataFrame({
    "Name":       ["Ann", "Bob"],
    "Age in Yrs": [30, 25],
})

df = df.rename(columns={"Name": "name", "Age in Yrs": "age"})
print(df.columns.tolist())

# The data is untouched, only the labels changed:
print(df.iloc[0].tolist())
# ['Ann', 30]

# ✅ Expected output:
# ['name', 'age']
# ['Ann', np.int64(30)]

2 Replacing Every Header — df.columns = [...]

When the whole header row is a mess, it is often quicker to overwrite it entirely. Assigning a list to df.columns replaces all the names at once. The catch: your list must have exactly one name per column, in the right order, or pandas raises a length-mismatch error.

df.columns = ["name", "age", "city"]   # must match the column count

# Clean an entire messy header in one expression using .str:
df.columns = (df.columns
                .str.strip()       # trim whitespace
                .str.lower()       # lowercase
                .str.replace(" ", "_"))   # spaces -> underscores
import pandas as pd

df = pd.DataFrame({
    "  First Name ": ["Ann"],
    "AGE":           [30],
    "Home City":     ["NYC"],
})

# Normalise the whole header in one chain of .str methods
df.columns = (df.columns
                .str.strip()
                .str.lower()
                .str.replace(" ", "_"))

print(df.columns.tolist())

# ✅ Expected output:
# ['first_name', 'age', 'home_city']

3 Tagging Columns — add_prefix & add_suffix

Sometimes you want to mark every column with a tag — a quarter, a source name, a units note. add_prefix() bolts a string onto the front of every column name, add_suffix() onto the back. Both return a new DataFrame and leave the values alone. They shine right before a merge, when you need to tell columns from two tables apart.

q1 = pd.DataFrame({"sales": [100], "cost": [60]})

q1.add_prefix("q1_")     # columns -> q1_sales, q1_cost
q1.add_suffix("_usd")    # columns -> sales_usd, cost_usd
import pandas as pd

q1 = pd.DataFrame({"sales": [100, 120], "cost": [60, 70]})

tagged = q1.add_prefix("q1_")
print(tagged.columns.tolist())

# suffix works the same way, on the other end
print(q1.add_suffix("_usd").columns.tolist())
# ['sales_usd', 'cost_usd']

# ✅ Expected output:
# ['q1_sales', 'q1_cost']
# ['sales_usd', 'cost_usd']
import pandas as pd

df = pd.DataFrame({"Full Name": ["Ann"], "YEARS": [30]})

# 🎯 YOUR TURN:
# Rename "Full Name" to "name" and "YEARS" to "age".
# Fill in the keyword argument that rename() uses for column labels.

df = df.rename(___={"Full Name": "name", "YEARS": "age"})
print(df.columns.tolist())

# Expected output:
# ['name', 'age']

! Common Errors (And How to Fix Them)

❌ "Length mismatch" assigning df.columns

The replacement list has the wrong number of names:

# df has 3 columns
df.columns = ["name", "age"]   # ❌ Length mismatch: 3 vs 2

✅ Fix: give exactly one name per column, or use rename:

df.columns = ["name", "age", "city"]              # ✅
df = df.rename(columns={"old": "name"})           # ✅ just one

Forgot to assign the result back (or a typo in the old name):

df.rename(columns={"Name": "name"})   # ❌ result discarded

✅ Fix: reassign the returned frame:

df = df.rename(columns={"Name": "name"})   # ✅

🎯 Mini Challenge: Tidy a Spreadsheet Header

An exported sheet has ugly headers. Clean them three ways.

import pandas as pd

df = pd.DataFrame({
    "Order ID": [1, 2],
    "Amt":      [100, 250],
    "Region":   ["N", "S"],
})

# 1) normalise the header
df.columns = df.columns.str.lower().str.replace(" ", "_")

# 2) fix one specific name
df = df.rename(columns={"amt": "amount"})

# 3) tag every column
df = df.add_prefix("q1_")

print(df.columns.tolist())

# ✅ Expected output:
# ['q1_order_id', 'q1_amount', 'q1_region']

❓ Frequently Asked Questions

Lesson complete — your labels are clean!

You can rename selected columns and index labels with rename, replace a whole header via df.columns, scrub names with .str methods, and tag them with add_prefix/add_suffix.

Practice quiz

How do you rename column A to x with rename()?

  • df.rename(columns={'A': 'x'})
  • df.rename(cols=['x'])
  • df.rename('A', 'x')
  • df.rename(rows={'A': 'x'})

Answer: df.rename(columns={'A': 'x'}). Pass a dict to the columns= argument: {'A': 'x'}.

What does rename() return by default?

  • None, it edits in place
  • A new DataFrame, leaving the original unchanged
  • Just the new column names
  • A boolean

Answer: A new DataFrame, leaving the original unchanged. rename() returns a new frame by default; use inplace=True to mutate.

How do you replace ALL column labels at once via the attribute?

  • df.columns.set(['x','y'])
  • df.relabel(['x','y'])
  • df.columns = ['x', 'y']
  • df.headers = ['x','y']

Answer: df.columns = ['x', 'y']. Assigning a list to df.columns replaces every column name.

Which call renames index labels rather than columns?

  • df.rename(columns={...})
  • df.rename(labels={...})
  • df.rename(rows={...})
  • df.rename(index={'r0': 'first'})

Answer: df.rename(index={'r0': 'first'}). Use the index= argument to rename row labels.

What does df.add_prefix('p_') do?

  • Adds 'p_' to the front of every column name
  • Adds a new column 'p_'
  • Prefixes every value with p_
  • Renames the index

Answer: Adds 'p_' to the front of every column name. add_prefix prepends the string to each column label.

What does df.add_suffix('_x') produce for column A?

  • x_A
  • A_x
  • A
  • _xA

Answer: A_x. add_suffix appends the string, turning A into A_x.

How do you lowercase every column name?

  • df.lower()
  • df.columns.lower()
  • df.rename(columns=str.lower)
  • df.tolower()

Answer: df.rename(columns=str.lower). Pass the function str.lower to columns= so it maps each name.

What does the inplace=True argument do in rename()?

  • Returns a copy
  • Renames only the first column
  • Reverses the names
  • Modifies the original DataFrame and returns None

Answer: Modifies the original DataFrame and returns None. inplace=True mutates the frame directly and returns None.

Which method sets new labels on a chosen axis?

  • df.set_axis(['x','y'], axis=1)
  • df.set_labels(['x','y'])
  • df.axis(['x','y'])
  • df.relabel_axis(['x','y'])

Answer: df.set_axis(['x','y'], axis=1). set_axis assigns new labels along axis=0 (rows) or axis=1 (columns).

If a key in the rename dict matches no column, what happens?

  • It raises a KeyError
  • That entry is ignored and other renames still apply
  • All columns are dropped
  • The frame becomes empty

Answer: That entry is ignored and other renames still apply. By default rename ignores keys that don't match; only matching labels change.

Continue this course

Frequently asked questions

What is the difference between rename() and assigning df.columns?

rename(columns={...}) changes only the labels you name and leaves the rest alone, so it is safe when you want to fix one or two columns. Assigning df.columns = [...] replaces the ENTIRE list at once, so the new list must have exactly the right length and order. Use rename for surgical edits and df.columns for a full relabel.

Does rename change the DataFrame in place?

No. By default rename() returns a new DataFrame and leaves the original unchanged. Assign the result back with df = df.rename(columns={...}), or pass inplace=True. Reassignment is the more common and readable style.

How do I clean every column name at once, like lowercasing them?

Use the .str methods on df.columns, which is itself an Index of strings. df.columns = df.columns.str.lower().str.replace(' ', '_') lowercases and replaces spaces in one expression. This is the standard way to normalise a whole header row imported from a messy spreadsheet.

What do add_prefix and add_suffix do?

They bolt a string onto the front or back of every column name. df.add_prefix('q1_') turns 'sales' into 'q1_sales', which is handy for tagging columns before a merge so you can tell which source they came from. They return a new DataFrame and never touch the data itself.