Use add_prefix() to add text before labels. It prefixes DataFrame columns by default and Series index labels. Choose the axis deliberately, preserve shared keys and check label uniqueness before combining data sources.
For a DataFrame, add_prefix() prefixes column labels by default. Col_ changes NAME to Col_NAME, not to name1. It changes labels rather than values and returns a new DataFrame.
import pandas as pd
df = 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]})
result = df.add_prefix("Col_")
print(result)
assert result.columns.tolist() == ["Col_NAME", "Col_ID", "Col_MATH", "Col_ENGLISH"]
assert df.columns.tolist() == ["NAME", "ID", "MATH", "ENGLISH"]Expected output
Col_NAME Col_ID Col_MATH Col_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 70For a Series, the row index labels are prefixed. This does not prepend text to the stored values or change the Series name.
s = pd.Series([1, 5, 7, 9, 10], name="score")
result = s.add_prefix("Ser_")
print(result)
assert result.index.tolist() == ["Ser_0", "Ser_1", "Ser_2", "Ser_3", "Ser_4"]
assert result.tolist() == s.tolist() and result.name == "score"Expected output
Ser_0 1
Ser_1 5
Ser_2 7
Ser_3 9
Ser_4 10
Name: score, dtype: int64axis="columns" prefixes columns and axis="index" prefixes rows for a DataFrame. The axis parameter is available from Pandas 2.0. Prefixing the index changes label-based selection and alignment.
table = pd.DataFrame({"amount": [12, 20]}, index=[101, 102])
print(table.add_prefix("sales_", axis="columns"))
print(table.add_prefix("order_", axis="index"))
assert table.add_prefix("order_", axis="index").index.tolist() == ["order_101", "order_102"]Expected output
sales_amount
101 12
102 20
amount
order_101 12
order_102 20To prefix values, operate on the column itself. Use a nullable string dtype to preserve missing values. For combining fields, see str.cat().
table = pd.DataFrame({"code": pd.Series(["0012", None], dtype="string")})
renamed = table.add_prefix("source_")
table["display_code"] = "SKU-" + table["code"]
print(renamed)
print(table)
assert renamed["source_code"].iloc[0] == "0012"
assert table["display_code"].iloc[0] == "SKU-0012"
assert pd.isna(table["display_code"].iloc[1])Expected output
source_code
0 0012
1 <NA>
code display_code
0 0012 SKU-0012
1 <NA> <NA>add_prefix() applies to the whole selected axis. Use rename() with a mapping when a join key must retain its name. Preserve one shared customer_id field and prefix the payload columns.
sales = pd.DataFrame({"customer_id": [101, 102], "amount": [12.5, 20], "status": ["paid", "paid"]})
mapping = {column: "sales_" + column for column in sales.columns if column != "customer_id"}
prepared = sales.rename(columns=mapping)
print(prepared)
assert prepared.columns.tolist() == ["customer_id", "sales_amount", "sales_status"]Expected output
customer_id sales_amount sales_status
0 101 12.5 paid
1 102 20.0 paidPrefixing does not repair duplicate labels. It also converts labels to string representations, which can collapse originally different labels such as integer 1 and string "1". Inspect columns before combining datasets.
table = pd.DataFrame([[5, 7]], columns=[1, "1"])
result = table.add_prefix("source_")
print(result)
print("Input labels unique:", table.columns.is_unique)
print("Output labels unique:", result.columns.is_unique)
assert table.columns.is_unique and not result.columns.is_uniqueExpected output
source_1 source_1
0 5 7
Input labels unique: True
Output labels unique: FalseThis synthetic example joins one customer table and one order-summary table with one row per customer. Prefix each source payload while keeping the common key intact. Validate key uniqueness before merging; naming columns does not validate the relationship.
customers = pd.DataFrame({"customer_id": [101, 102], "name": ["Ravi", "Alex"], "status": ["active", "inactive"]})
summary = pd.DataFrame({"customer_id": [101, 102], "amount": [12.5, 20], "status": ["paid", "pending"]})
def prefix_payload(table, prefix, key):
assert table.columns.is_unique
assert table[key].notna().all() and table[key].is_unique
mapping = {column: prefix + str(column) for column in table.columns if column != key}
result = table.rename(columns=mapping)
assert result.columns.is_unique
return result
left = prefix_payload(customers, "customer_", "customer_id")
right = prefix_payload(summary, "sales_", "customer_id")
combined = left.merge(right, on="customer_id", how="left", validate="one_to_one", indicator=True)
print(combined)
assert combined.columns.is_unique and len(combined) == 2
assert combined["_merge"].eq("both").all()Expected output
customer_id customer_name customer_status sales_amount sales_status _merge
0 101 Ravi active 12.5 paid both
1 102 Alex inactive 20.0 pending bothConfirm that source-specific statuses remain separate and keys are preserved. The merge indicator exposes unmatched customers. Keep naming maps when downstream reports depend on a stable schema.
expected = ["customer_id", "customer_name", "customer_status", "sales_amount", "sales_status", "_merge"]
assert combined.columns.tolist() == expected
assert combined["customer_status"].tolist() == ["active", "inactive"]
assert combined["sales_status"].tolist() == ["paid", "pending"]
print(combined.drop(columns="_merge").to_csv(index=False).rstrip())
# Optional Colab export:
# combined.drop(columns="_merge").to_csv("named_customer_sales.csv", index=False)Expected output
customer_id,customer_name,customer_status,sales_amount,sales_status
101,Ravi,active,12.5,paid
102,Alex,inactive,20.0,pendingRepeated calls add repeated prefixes. If your process receives both prefixed and unprefixed labels, define a naming rule and check for collisions after conditional renaming. Do not blindly strip prefixes that may be meaningful.
table = pd.DataFrame({"amount": [5], "sales_status": ["paid"]})
mapping = {column: column if column.startswith("sales_") else "sales_" + column for column in table.columns}
result = table.rename(columns=mapping)
assert result.columns.is_unique
print(result)
print("Repeated prefix on amount:", table[["amount"]].add_prefix("sales_").add_prefix("sales_").columns.tolist())Expected output
sales_amount sales_status
0 5 paid
Repeated prefix on amount: ['sales_sales_amount']Use add_prefix() for an entire axis, add_suffix() for trailing label text, and rename() for selective or arbitrary label changes. For row labels, consider whether changing them will disrupt loc selection or alignment. These methods organise labels; they do not clean the stored values.
Does add_prefix() change cell values? No. Is there inplace=True? No; use the returned object. Why did my numeric index become text? The prefix forms string labels. Can I prefix only two columns? Use a rename mapping or select and combine deliberately. Does prefixing fix duplicate columns? No; check label uniqueness. Should I prefix join keys? Preserve the shared key or explicitly adapt the merge arguments. Does a prefix guarantee compatible data? No; still validate types and business relationships.
Create a table with id, math and english. Keep id unchanged and rename the two measurement fields to exam_math and exam_english. Check that all values and the original table remain unchanged.
Use an explicit mapping to leave the identifier untouched.
practice = pd.DataFrame({"id": [1, 2], "math": [75, 85], "english": [70, 80]})
answer = practice.rename(columns={"math": "exam_math", "english": "exam_english"})
print(answer)
assert answer.columns.tolist() == ["id", "exam_math", "exam_english"]
assert practice.columns.tolist() == ["id", "math", "english"]
assert answer["exam_math"].equals(practice["math"])Expected output
id exam_math exam_english
0 1 75 70
1 2 85 80Open in Google Colab View on GitHub
Run the examples in order, change prefixes and selected fields, then inspect the output labels and preserved keys. Save your own copy to keep edits. All sample tables are included in the notebook.
Continue with the Data Cleaning hub, column inspection, rename() and add_suffix().
Reference: Pandas DataFrame.add_prefix documentation.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.