Pandas rename(): Standardise Columns and Index Labels

Use rename() to change column labels or row index labels with a mapping or callable. Choose the axis explicitly, detect missing source labels and check the proposed names for collisions before applying a schema change.

Rename selected columns with a mapping 🔝

Specify columns explicitly to change field labels. Unlisted columns remain unchanged. The default returns a new DataFrame; it does not change stored values.

import pandas as pd
def student_data():
    return pd.DataFrame({"NAME": ["Ravi", "Raju", "Alex", "Ron", "King", "Jack"], "ID": [1, 2, 3, 4, 5, 6], "MATH": [30, 40, 50, 60, 70, 80], "ENGLISH": [20, 30, 40, 50, 60, 70]})
df = student_data()
result = df.rename(columns={"NAME": "name1", "ENGLISH": "eng"})
print(result)
assert result.columns.tolist() == ["name1", "ID", "MATH", "eng"]
assert df.columns.tolist() == ["NAME", "ID", "MATH", "ENGLISH"]

Expected output

  name1  ID  MATH  eng
0  Ravi   1    30   20
1  Raju   2    40   30
2  Alex   3    50   40
3   Ron   4    60   50
4  King   5    70   60
5  Jack   6    80   70

Rename row labels and understand inplace 🔝

index changes row labels rather than the values in an ID column. With inplace=True, the source object changes and the method returns None. Do not assign that return value back to df.

df = student_data()
returned = df.rename(index={0: "a", 1: "b"}, inplace=True)
print(df)
print("Return value:", returned)
assert returned is None
assert df.index.tolist() == ["a", "b", 2, 3, 4, 5]
assert df["ID"].tolist() == [1, 2, 3, 4, 5, 6]

Expected output

   NAME  ID  MATH  ENGLISH
a  Ravi   1    30       20
b  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
5  Jack   6    80       70
Return value: None

Apply a callable to column labels 🔝

Use str.lower with axis="columns" to lowercase existing string labels. This changes labels only, not names stored in cells. For mixed-type labels, first decide whether converting labels to text is appropriate.

df = student_data()
result = df.rename(str.lower, axis="columns")
print(result)
assert result.columns.tolist() == ["name", "id", "math", "english"]
assert result["name"].tolist() == df["NAME"].tolist()

Expected output

   name  id  math  english
0  Ravi   1    30       20
1  Raju   2    40       30
2  Alex   3    50       40
3   Ron   4    60       50
4  King   5    70       60
5  Jack   6    80       70

Choose mapper plus axis or explicit columns/index 🔝

The mapper form defaults to the row index, so specify axis when renaming columns. columns and index are clearer for many selective changes; do not mix conflicting forms.

df = student_data()
mapped = df.rename({"NAME": "name"}, axis=1)
explicit = df.rename(columns={"NAME": "name"})
assert mapped.equals(explicit)
print(explicit.head(2))
print("Default mapper leaves NAME unchanged:", df.rename({"NAME": "name"}).columns.tolist())

Expected output

   name  ID  MATH  ENGLISH
0  Ravi   1    30       20
1  Raju   2    40       30
Default mapper leaves NAME unchanged: ['NAME', 'ID', 'MATH', 'ENGLISH']

Detect missing source labels with errors="raise" 🔝

The default errors="ignore" ignores mapping keys absent from the selected axis. Use errors="raise" for a required schema migration so typos are visible. This does not detect collisions between target names.

df = student_data()
try:
    df.rename(columns={"NAM": "name"}, errors="raise")
except KeyError as error:
    print(type(error).__name__ + ": " + str(error))
result = df.rename(columns={"NAME": "name"}, errors="raise")
print(result.columns.tolist())
assert "name" in result.columns

Expected output

KeyError: "['NAM'] not found in axis"
['name', 'ID', 'MATH', 'ENGLISH']

Check target labels for collisions 🔝

Renaming can create duplicate columns, including a collision with a column not listed in the mapping. Inspect the proposed labels before applying the change. Column validation explains why duplicate labels make selection ambiguous.

df = pd.DataFrame({"amount": [5], "total": [7]})
mapping = {"amount": "total"}
proposed = pd.Index([mapping.get(column, column) for column in df.columns])
print("Proposed labels:", proposed.tolist())
print("Unique:", proposed.is_unique)
assert not proposed.is_unique
# Resolve the naming conflict before calling rename().

Expected output

Proposed labels: ['total', 'total']
Unique: False

Rename one level of MultiIndex columns 🔝

level targets an existing label level. This changes values within that level, not its descriptive name. Use rename_axis() for axis names. Preserve the hierarchy unless a flat schema is explicitly required.

columns = pd.MultiIndex.from_tuples([("sales", "jan"), ("sales", "feb"), ("cost", "jan")], names=["metric", "month"])
df = pd.DataFrame([[12, 20, 5]], columns=columns)
result = df.rename(columns={"jan": "January", "feb": "February"}, level="month")
print(result)
assert result.columns.names == ["metric", "month"]
assert result.columns.get_level_values("month").tolist() == ["January", "February", "January"]

Expected output

metric   sales             cost
month  January February January
0           12       20       5

Practical workflow: standardise an imported sales schema 🔝

This synthetic extract has spaces and inconsistent field labels. Normalise labels into a helper list, check collisions, then apply an explicit semantic mapping. A label called Amount is not automatically a valid numeric amount; type conversion is a separate step.

raw = pd.DataFrame({" Order ID ": pd.Series(["0012", "0045"], dtype="string"), " Product Name ": ["Pen", "Book"], "Amount ": ["5.50", "bad"]})
normalised_labels = pd.Index([str(column).strip().lower().replace(" ", "_") for column in raw.columns])
assert raw.columns.is_unique and normalised_labels.is_unique
normalisation_map = dict(zip(raw.columns, normalised_labels))
staged = raw.rename(columns=normalisation_map, errors="raise")
semantic_map = {"product_name": "product", "amount": "sales_amount"}
proposed = pd.Index([semantic_map.get(column, column) for column in staged.columns])
assert proposed.is_unique
cleaned = staged.rename(columns=semantic_map, errors="raise")
print(cleaned)
print("Naming map:", normalisation_map)
assert cleaned.columns.tolist() == ["order_id", "product", "sales_amount"]
assert cleaned["order_id"].iloc[0] == "0012"

Expected output

  order_id product sales_amount
0     0012     Pen         5.50
1     0045    Book          bad
Naming map: {' Order ID ': 'order_id', ' Product Name ': 'product_name', 'Amount ': 'amount'}

Validate the renamed schema and review conversion failures 🔝

Verify required labels before calculations. Keep invalid raw values in a review table. See type conversion, dtype selection and missing-value audits.

required = {"order_id", "product", "sales_amount"}
assert required.issubset(cleaned.columns) and cleaned.columns.is_unique
amount = pd.to_numeric(cleaned["sales_amount"], errors="coerce")
valid = amount.notna() & amount.ge(0)
accepted = cleaned.loc[valid].copy()
accepted["sales_amount"] = amount.loc[valid]
review = cleaned.loc[~valid].copy()
print("Accepted:")
print(accepted)
print("Review:")
print(review)
assert accepted["order_id"].tolist() == ["0012"]
# Optional Colab export:
# accepted.to_csv("renamed_sales.csv", index=False)

Expected output

Accepted:
  order_id product  sales_amount
0     0012     Pen           5.5
Review:
  order_id product sales_amount
1     0045    Book          bad

Choose rename(), prefixing or suffixing 🔝

Use rename() for selected labels or callable transformations. add_prefix() and add_suffix() apply the same leading or trailing text across an axis. Renaming is not value replacement, dtype conversion or unit conversion. Inspect row labels after changes before using loc.

Common questions 🔝

Why was a name not changed? Check the selected axis, exact spelling and surrounding spaces. Does errors="raise" guarantee unique target names? No; check target labels separately. Does rename() change row order? No. How do I change the index name? Use rename_axis(); rename(index=...) changes index labels. Can I use inplace=True? Yes; it returns None. Should I pass copy=True? The copy argument is deprecated and ignored in Pandas 3.0; these examples omit it. Does a cleaned label make its column valid? No; inspect values and types separately.

Exercise: rename two fields without changing a key 🔝

Create columns id, MATH and ENGLISH. Rename them to id, math_score and english_score, using errors="raise". Confirm the source column names and values remain unchanged.

Exercise solution 🔝

An explicit mapping leaves id untouched. Verify both the target schema and the source.

practice = pd.DataFrame({"id": [1, 2], "MATH": [75, 85], "ENGLISH": [70, 80]})
answer = practice.rename(columns={"MATH": "math_score", "ENGLISH": "english_score"}, errors="raise")
print(answer)
assert answer.columns.tolist() == ["id", "math_score", "english_score"]
assert practice.columns.tolist() == ["id", "MATH", "ENGLISH"]
assert answer["math_score"].equals(practice["MATH"])

Expected output

   id  math_score  english_score
0   1          75             70
1   2          85             80

Practice in Google Colab 🔝

Open in Google Colab View on GitHub
Run the examples in order, change mappings and imported labels, then inspect the output schema and naming collisions. Save your own copy to keep edits. All sample tables are included in the notebook.

Continue with the Data Cleaning hub, Pandas Input and Output, column inspection, add_prefix() and add_suffix().

Reference: Pandas DataFrame.rename documentation.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer