Pandas - Rename Column Names

The `rename()` method is the most versatile approach for changing column names in Pandas. It accepts a dictionary mapping old names to new names and returns a new DataFrame by default.

Key Insights

  • Pandas offers multiple methods to rename columns: rename() for selective changes, direct assignment for complete replacement, and add_prefix()/add_suffix() for bulk modifications
  • The rename() method provides both dictionary-based and function-based approaches, with an inplace parameter to modify DataFrames directly or return new copies
  • Column renaming is critical for data cleaning workflows, especially when handling datasets with inconsistent naming conventions, spaces, or special characters

Basic Column Renaming with rename()

The rename() method is the most versatile approach for changing column names in Pandas. It accepts a dictionary mapping old names to new names and returns a new DataFrame by default.

import pandas as pd

df = pd.DataFrame({
    'First Name': ['John', 'Jane', 'Bob'],
    'Last Name': ['Doe', 'Smith', 'Johnson'],
    'Age': [28, 34, 45]
})

# Rename specific columns using a dictionary
df_renamed = df.rename(columns={
    'First Name': 'first_name',
    'Last Name': 'last_name',
    'Age': 'age'
})

print(df_renamed.columns)
# Output: Index(['first_name', 'last_name', 'age'], dtype='object')

The original DataFrame remains unchanged unless you use the inplace=True parameter:

df.rename(columns={'First Name': 'first_name'}, inplace=True)
print(df.columns)
# Output: Index(['first_name', 'Last Name', 'Age'], dtype='object')

Using Functions for Dynamic Renaming

Instead of a dictionary, pass a function to rename() for pattern-based transformations. This approach excels when applying consistent formatting rules across all columns.

df = pd.DataFrame({
    'First Name': ['John', 'Jane'],
    'Last Name': ['Doe', 'Smith'],
    'Email Address': ['john@example.com', 'jane@example.com']
})

# Convert all column names to lowercase and replace spaces
df_clean = df.rename(columns=lambda x: x.lower().replace(' ', '_'))
print(df_clean.columns)
# Output: Index(['first_name', 'last_name', 'email_address'], dtype='object')

# Remove whitespace and convert to snake_case
import re

def to_snake_case(name):
    name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', name)
    name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', name)
    return name.lower().replace(' ', '_')

df_snake = df.rename(columns=to_snake_case)

Direct Column Assignment

For complete column replacement, assign a new list directly to the columns attribute. This method requires providing names for all columns.

df = pd.DataFrame({
    'A': [1, 2, 3],
    'B': [4, 5, 6],
    'C': [7, 8, 9]
})

# Replace all column names
df.columns = ['col_1', 'col_2', 'col_3']
print(df.columns)
# Output: Index(['col_1', 'col_2', 'col_3'], dtype='object')

This approach is efficient but risky—if the list length doesn’t match the number of columns, Pandas raises a ValueError:

df = pd.DataFrame({'A': [1, 2], 'B': [3, 4], 'C': [5, 6]})

try:
    df.columns = ['col_1', 'col_2']  # Only 2 names for 3 columns
except ValueError as e:
    print(f"Error: {e}")
# Output: Error: Length mismatch: Expected axis has 3 elements, new values have 2 elements

Adding Prefixes and Suffixes

The add_prefix() and add_suffix() methods provide quick bulk modifications without affecting existing names.

df = pd.DataFrame({
    'revenue': [1000, 1500, 2000],
    'cost': [600, 800, 1100],
    'profit': [400, 700, 900]
})

# Add prefix to all columns
df_prefixed = df.add_prefix('q1_')
print(df_prefixed.columns)
# Output: Index(['q1_revenue', 'q1_cost', 'q1_profit'], dtype='object')

# Add suffix to all columns
df_suffixed = df.add_suffix('_usd')
print(df_suffixed.columns)
# Output: Index(['revenue_usd', 'cost_usd', 'profit_usd'], dtype='object')

Combine these methods with column selection for targeted modifications:

# Add suffix only to numeric columns
numeric_cols = df.select_dtypes(include=['number']).columns
df[numeric_cols] = df[numeric_cols].add_suffix('_amount')

Renaming with str Methods

Access string methods on column names using df.columns.str for advanced text manipulation.

df = pd.DataFrame({
    '  First Name  ': ['John', 'Jane'],
    'LAST_NAME': ['Doe', 'Smith'],
    'email@address': ['john@ex.com', 'jane@ex.com']
})

# Strip whitespace
df.columns = df.columns.str.strip()

# Convert to lowercase
df.columns = df.columns.str.lower()

# Replace special characters
df.columns = df.columns.str.replace('@', '_at_')
df.columns = df.columns.str.replace('[^a-z0-9_]', '_', regex=True)

print(df.columns)
# Output: Index(['first_name', 'last_name', 'email_at_address'], dtype='object')

Chain multiple operations for comprehensive cleaning:

df.columns = (df.columns
              .str.strip()
              .str.lower()
              .str.replace(' ', '_')
              .str.replace('[^a-z0-9_]', '', regex=True))

Renaming During Data Import

Set column names during CSV or Excel import to avoid post-processing steps.

# Rename columns while reading CSV
df = pd.read_csv('data.csv', names=['col1', 'col2', 'col3'], header=0)

# Use header=None if the file has no header row
df = pd.read_csv('data.csv', names=['id', 'name', 'value'], header=None)

# Rename specific columns after import
df = pd.read_csv('data.csv')
df = df.rename(columns={'old_name': 'new_name'})

Handling MultiIndex Columns

For DataFrames with hierarchical column structures, rename specific levels using the level parameter.

arrays = [
    ['A', 'A', 'B', 'B'],
    ['one', 'two', 'one', 'two']
]
df = pd.DataFrame([[1, 2, 3, 4]], columns=pd.MultiIndex.from_arrays(arrays))

# Rename top level
df = df.rename(columns={'A': 'Group_A', 'B': 'Group_B'}, level=0)

# Rename bottom level
df = df.rename(columns={'one': 'first', 'two': 'second'}, level=1)

print(df.columns)
# Output: MultiIndex([('Group_A',  'first'),
#                     ('Group_A', 'second'),
#                     ('Group_B',  'first'),
#                     ('Group_B', 'second')])

Common Patterns and Best Practices

Create reusable functions for consistent naming conventions across projects:

def clean_column_names(df):
    """Standardize column names to snake_case."""
    df = df.copy()
    df.columns = (df.columns
                  .str.strip()
                  .str.lower()
                  .str.replace(' ', '_')
                  .str.replace('[^a-z0-9_]', '', regex=True)
                  .str.replace('_+', '_', regex=True))
    return df

# Apply to any DataFrame
df_clean = clean_column_names(df)

Handle duplicate column names that may arise during renaming:

df = pd.DataFrame([[1, 2, 3]], columns=['a', 'b', 'a'])

# Pandas automatically handles duplicates during creation
print(df.columns)
# Output: Index(['a', 'b', 'a'], dtype='object')

# Make unique by adding suffixes
df.columns = pd.io.parsers.ParserBase({'names': df.columns})._maybe_dedup_names(df.columns)

For production pipelines, validate column names after renaming:

def validate_columns(df, expected_columns):
    """Ensure DataFrame has expected column names."""
    missing = set(expected_columns) - set(df.columns)
    extra = set(df.columns) - set(expected_columns)
    
    if missing or extra:
        raise ValueError(f"Column mismatch. Missing: {missing}, Extra: {extra}")
    return df

expected = ['id', 'name', 'value']
df = validate_columns(df, expected)

Column renaming is fundamental to data preparation. Choose rename() for selective changes, direct assignment for complete replacement, and string methods for pattern-based transformations. Always validate results in production environments to catch schema mismatches early.

Liked this? There's more.

Every week: one practical technique, explained simply, with code you can use immediately.