How do I add a prefix or suffix to every column name in pandas?
Short answer
Use add_prefix or add_suffix to tag every column at once, which is useful before merging two frames with overlapping names. Use rename for selective changes instead.
The short version
add_prefix("x_") and add_suffix("_x") rename every column in one call. The commonest use is tagging columns before merging two frames that share names, so you can tell which side each column came from without relying on the automatic _x and _y suffixes.
The basic call
import pandas as pd
df = pd.DataFrame({"city": ["Leeds"], "amount": [10]})
print(df.add_prefix("col_").columns.tolist()) # ['col_city', 'col_amount']
print(df.add_suffix("_2021").columns.tolist()) # ['city_2021', 'amount_2021']
Every column is renamed, with no dictionary to write out.
Why this beats the automatic merge suffixes
When two frames share column names, a merge tags the clashes with _x and _y, which tells you nothing about what the columns mean. Tagging them yourself first gives meaningful names.
this_year = this_year.add_suffix("_2021")
last_year = last_year.add_suffix("_2020")
Now a comparison table has amount_2021 and amount_2020, which any reader understands immediately.
Keeping the join key untagged
The catch is that add_prefix renames the key column too, which then breaks the merge. Set the key as the index first, so it is not touched, then reset it afterwards.
tagged = df.set_index("city").add_suffix("_2021").reset_index()
The index is not a column, so it escapes the renaming, and city comes back with its original name. This is the standard way to tag every column except the key.
Renaming only some columns
For selective changes, rename with a dictionary is the right tool, because it leaves everything not mentioned alone.
df.rename(columns={"amount": "total"})
Use add_prefix when the rule applies to every column, and rename when it applies to a few.
Applying a rule to every name
For a transformation rather than a fixed prefix, operate on the columns directly.
df.columns = df.columns.str.lower().str.replace(" ", "_")
This is the general form, useful for tidying inconsistent headers, and add_prefix is just a convenient special case of the same idea.
On Series
add_prefix on a Series renames the index labels rather than columns, since a Series has no columns. That is occasionally handy after a groupby, but it surprises people who expect it to do nothing, so keep the distinction in mind.