Pandas add_suffix(): Name Columns and Index Labels

Use add_suffix() to append text to labels. It changes DataFrame column labels by default and Series index labels. Preserve shared keys, distinguish naming from value conversion and check collisions before combining datasets.

Suffix DataFrame column labels 🔝

For a DataFrame, add_suffix() appends text to column labels by default. _Col changes NAME to NAME_Col, not to name1. The method returns a new object and does not change cell values.

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_suffix("_Col")
print(result)
assert result.columns.tolist() == ["NAME_Col", "ID_Col", "MATH_Col", "ENGLISH_Col"]
assert df.columns.tolist() == ["NAME", "ID", "MATH", "ENGLISH"]

Expected output

  NAME_Col  ID_Col  MATH_Col  ENGLISH_Col
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

Suffix Series index labels 🔝

For a Series, add_suffix() changes row labels. The values and Series name remain unchanged. Labels that were integers become strings after a suffix is added.

s = pd.Series([1, 5, 7, 9, 10], name="score")
result = s.add_suffix("_Ser")
print(result)
assert result.index.tolist() == ["0_Ser", "1_Ser", "2_Ser", "3_Ser", "4_Ser"]
assert result.tolist() == s.tolist() and result.name == "score"

Expected output

0_Ser     1
1_Ser     5
2_Ser     7
3_Ser     9
4_Ser    10
Name: score, dtype: int64

Choose columns or the row index 🔝

Use axis="columns" or axis="index" explicitly for a DataFrame. The axis parameter is available from Pandas 2.0. Changing index labels can affect loc selection and alignment.

table = pd.DataFrame({"amount": [12, 20]}, index=[101, 102])
print(table.add_suffix("_sales", axis="columns"))
print(table.add_suffix("_order", axis="index"))
assert table.add_suffix("_order", axis="index").index.tolist() == ["101_order", "102_order"]

Expected output

     amount_sales
101            12
102            20
           amount
101_order      12
102_order      20

Distinguish label suffixes from value suffixes 🔝

To append text to cell values, operate on the column itself. A label ending in _kg does not convert a stored measurement to kilograms: unit conversion requires a separate calculation. See combining text values.

table = pd.DataFrame({"weight": [2.5, 3.0]})
labelled = table.add_suffix("_kg")
print(labelled)
assert labelled["weight_kg"].equals(table["weight"])
codes = pd.Series(["0012", None], dtype="string")
print(codes + "-A")
assert pd.isna((codes + "-A").iloc[1])

Expected output

   weight_kg
0        2.5
1        3.0
0    0012-A
1      <NA>
dtype: string

Suffix measurement fields while preserving the key 🔝

add_suffix() changes an entire axis. Use rename() with a mapping when only selected fields should change. Keep shared identifiers unchanged unless the join arguments explicitly account for their new names.

table = pd.DataFrame({"product_id": ["0012", "0045"], "quantity": [2, 3], "revenue": [11.0, 24.0]})
mapping = {column: str(column) + "_jan" for column in table.columns if column != "product_id"}
result = table.rename(columns=mapping)
print(result)
assert result.columns.tolist() == ["product_id", "quantity_jan", "revenue_jan"]

Expected output

  product_id  quantity_jan  revenue_jan
0       0012             2         11.0
1       0045             3         24.0

Check label uniqueness before and after renaming 🔝

Suffixing does not fix duplicated labels. Different original labels can also share the same string representation. Selective suffixing may collide with existing names, so validate the result before use.

table = pd.DataFrame([[5, 7]], columns=[1, "1"])
result = table.add_suffix("_source")
print(result)
print("Original labels unique:", table.columns.is_unique)
print("New labels unique:", result.columns.is_unique)
assert table.columns.is_unique and not result.columns.is_unique
partial = pd.DataFrame({"amount": [5], "amount_jan": [7]}).rename(columns={"amount": "amount_jan"})
assert not partial.columns.is_unique

Expected output

   1_source  1_source
0         5         7
Original labels unique: True
New labels unique: False

Practical workflow: compare two monthly summaries 🔝

These synthetic tables contain one row per product per month. Append a month suffix to the payload fields and preserve product_id for the merge. An outer merge retains products present in only one month. Missing values are not automatically zero sales.

jan = pd.DataFrame({"product_id": ["0012", "0045"], "quantity": [2, 3], "revenue": [11.0, 24.0]})
feb = pd.DataFrame({"product_id": ["0012", "0070"], "quantity": [4, 1], "revenue": [22.0, 6.0]})
def suffix_payload(table, suffix, key):
    assert table.columns.is_unique
    assert table[key].notna().all() and table[key].is_unique
    mapping = {column: str(column) + suffix for column in table.columns if column != key}
    result = table.rename(columns=mapping)
    assert result.columns.is_unique
    return result
left = suffix_payload(jan, "_jan", "product_id")
right = suffix_payload(feb, "_feb", "product_id")
combined = left.merge(right, on="product_id", how="outer", validate="one_to_one", indicator=True)
print(combined)
assert len(combined) == 3 and combined.columns.is_unique

Expected output

  product_id  quantity_jan  revenue_jan  quantity_feb  revenue_feb      _merge
0       0012           2.0         11.0           4.0         22.0        both
1       0045           3.0         24.0           NaN          NaN   left_only
2       0070           NaN          NaN           1.0          6.0  right_only

Calculate changes only where both months exist 🔝

Use the merge indicator to identify comparable products. Keep unmatched products for review. Interpreting missing as zero requires confirmation that the source extract covers all products and that absence means no sales.

both = combined["_merge"].eq("both")
comparison = combined.loc[both].copy()
comparison["revenue_change"] = comparison["revenue_feb"] - comparison["revenue_jan"]
print(comparison[["product_id", "revenue_jan", "revenue_feb", "revenue_change"]])
print("Products in only one extract:")
print(combined.loc[~both])
assert comparison["product_id"].tolist() == ["0012"]
assert comparison["revenue_change"].iloc[0] == 11

Expected output

  product_id  revenue_jan  revenue_feb  revenue_change
0       0012         11.0         22.0            11.0
Products in only one extract:
  product_id  quantity_jan  revenue_jan  quantity_feb  revenue_feb      _merge
1       0045           3.0         24.0           NaN          NaN   left_only
2       0070           NaN          NaN           1.0          6.0  right_only

Validate the output schema and export 🔝

Confirm each measurement retains its month and the identifiers retain leading zeros. Keep the merge indicator in an audit export. See column inspection and Excel export.

expected = ["product_id", "quantity_jan", "revenue_jan", "quantity_feb", "revenue_feb", "_merge"]
assert combined.columns.tolist() == expected
assert combined["product_id"].is_unique
print(combined.to_csv(index=False).rstrip())
# Optional Colab exports:
# combined.to_csv("monthly_product_audit.csv", index=False)
# comparison.to_csv("comparable_product_changes.csv", index=False)

Expected output

product_id,quantity_jan,revenue_jan,quantity_feb,revenue_feb,_merge
0012,2.0,11.0,4.0,22.0,both
0045,3.0,24.0,,,left_only
0070,,,1.0,6.0,right_only

Avoid adding the same suffix twice 🔝

Repeated calls append the suffix again. Conditional naming can help with mixed input schemas, but check for collisions after renaming. Preserve a naming map when downstream files depend on fixed labels.

table = pd.DataFrame({"amount": [5], "status_jan": ["paid"]})
mapping = {column: column if column.endswith("_jan") else column + "_jan" for column in table.columns}
result = table.rename(columns=mapping)
assert result.columns.is_unique
print(result)
print("Repeated suffix:", table[["amount"]].add_suffix("_jan").add_suffix("_jan").columns.tolist())

Expected output

   amount_jan status_jan
0           5       paid
Repeated suffix: ['amount_jan_jan']

Choose suffixing, prefixing or an explicit rename 🔝

Use add_suffix() to change every label on an axis, add_prefix() for leading label text, and rename() for selected or arbitrary changes. Merge suffixes only disambiguate overlapping column names; proactively naming all payload columns can make the source or period clearer. Naming does not convert types, validate units or establish compatible business definitions.

Common questions 🔝

Does add_suffix() change values? No. Is there inplace=True? No; store the returned object. Can I suffix just two fields? Use an explicit rename mapping. Does a month suffix prove a complete monthly extract? No; verify coverage and period separately. Why did the row index become text? A suffix forms string labels. Does suffixing remove duplicate labels? No. What about MultiIndex columns? Inspect the tuple structure and rename the intended level deliberately rather than treating a multi-level schema as flat labels.

Exercise: suffix measurements only 🔝

Create columns id, math and english. Keep id unchanged and rename the measurements to math_exam and english_exam. Verify the original table is unchanged.

Exercise solution 🔝

An explicit mapping preserves the key and communicates which labels change.

practice = pd.DataFrame({"id": [1, 2], "math": [75, 85], "english": [70, 80]})
answer = practice.rename(columns={"math": "math_exam", "english": "english_exam"})
print(answer)
assert answer.columns.tolist() == ["id", "math_exam", "english_exam"]
assert practice.columns.tolist() == ["id", "math", "english"]
assert answer["math_exam"].equals(practice["math"])

Expected output

   id  math_exam  english_exam
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 suffixes and monthly data, then compare labels, unmatched products and calculated changes. 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_prefix().

Reference: Pandas DataFrame.add_suffix 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