When working with real-world datasets, you may encounter DataFrames that contain duplicate columns - columns with identical data but potentially different names, or columns with the same name created during merges and concatenations. Identifying and removing these duplicates is essential for clean data analysis and avoiding redundant computations.
This guide covers how to detect duplicate columns in a Pandas DataFrame and demonstrates multiple methods to drop them, with clear examples and outputs for each approach.
Creating a Sample DataFrame
Let's start with a DataFrame that intentionally contains a duplicate column: the Marks column has the exact same values as the Age column.
import pandas as pd
students = [
("Michael", 34, "California", 34),
("Emily", 30, "Texas", 30),
("Jacob", 16, "Florida", 16),
("Emily", 30, "New York", 30),
("Olivia", 40, "Illinois", 40),
("Daniel", 30, "Washington", 30),
]
df = pd.DataFrame(students, columns=["Name", "Age", "Domicile", "Marks"])
print(df)Output:
Name Age Domicile Marks
0 Michael 34 California 34
1 Emily 30 Texas 30
2 Jacob 16 Florida 16
3 Emily 30 New York 30
4 Olivia 40 Illinois 40
5 Daniel 30 Washington 3Notice that Age and Marks contain identical values in every row - Marks is a duplicate of Age.
Finding Duplicate Columns
Before dropping duplicates, you'll want to identify which columns are duplicated. There are two types of duplication to detect:
- Duplicate column names - columns with the same header label.
- Duplicate column content - columns with different names but identical data.
Detecting Columns with Identical Content
This custom function compares every column against every other column and identifies those with matching content:
import pandas as pd
students = [
("Michael", 34, "California", 34),
("Emily", 30, "Texas", 30),
("Jacob", 16, "Florida", 16),
("Emily", 30, "New York", 30),
("Olivia", 40, "Illinois", 40),
("Daniel", 30, "Washington", 30),
]
df = pd.DataFrame(students, columns=["Name", "Age", "Domicile", "Marks"])
def get_duplicate_columns(df):
"""Return a list of column names that have duplicate content."""
duplicate_columns = set()
for i in range(df.shape[1]):
col_i = df.iloc[:, i]
for j in range(i + 1, df.shape[1]):
col_j = df.iloc[:, j]
if col_i.equals(col_j):
duplicate_columns.add(df.columns[j])
return list(duplicate_columns)
duplicates = get_duplicate_columns(df)
print(f"Duplicate columns: {duplicates}")Output:
Duplicate columns: ['Marks']The function correctly identifies that Marks is a content-duplicate of Age.
Detecting Duplicate Column Names
If your DataFrame has columns with the same name (common after merges), use df.columns.duplicated():
import pandas as pd
students = [
("Michael", 34, "California", 34),
("Emily", 30, "Texas", 30),
("Jacob", 16, "Florida", 16),
("Emily", 30, "New York", 30),
("Olivia", 40, "Illinois", 40),
("Daniel", 30, "Washington", 30),
]
df = pd.DataFrame(students, columns=["Name", "Age", "Domicile", "Marks"])
df_dup_names = pd.DataFrame(
[[1, 2, 3], [4, 5, 6]],
columns=["A", "B", "A"]
)
print("Duplicate column names:")
print(df_dup_names.columns[df_dup_names.columns.duplicated()].tolist())Output:
Duplicate column names:
['A']Method 1: Drop Duplicate Content Using Transpose and drop_duplicates()
A concise approach is to transpose the DataFrame (swap rows and columns), apply drop_duplicates() to remove duplicate rows (which were originally duplicate columns), then transpose back:
import pandas as pd
students = [
("Michael", 34, "California", 34),
("Emily", 30, "Texas", 30),
("Jacob", 16, "Florida", 16),
("Emily", 30, "New York", 30),
("Olivia", 40, "Illinois", 40),
("Daniel", 30, "Washington", 30),
]
df = pd.DataFrame(students, columns=["Name", "Age", "Domicile", "Marks"])
df_clean = df.T.drop_duplicates().T
print(df_clean)Output:
Name Age Domicile
0 Michael 34 California
1 Emily 30 Texas
2 Jacob 16 Florida
3 Emily 30 New York
4 Olivia 40 Illinois
5 Daniel 30 WashingtonThe Marks column has been removed because its content is identical to Age.
Method 2: Drop Duplicate Column Names Using df.loc[]
If your duplicate columns share the same name, use df.columns.duplicated() with loc[] to keep only the first occurrence:
import pandas as pd
df_dup = pd.DataFrame(
{"A": [1, 2, 3], "B": [4, 5, 6], "A_dup": [1, 2, 3]},
)
df_dup.columns = ["A", "B", "A"] # Force duplicate names
print("Before:")
print(df_dup)
df_clean = df_dup.loc[:, ~df_dup.columns.duplicated()]
print("\nAfter:")
print(df_clean)Output:
Before:
A B A
0 1 4 1
1 2 5 2
2 3 6 3
After:
A B
0 1 4
1 2 5
2 3 6df.columns.duplicated()returns a boolean array -Truefor column names that have appeared before.- The
~operator negates it, selecting only the first occurrence of each name. df.loc[:, mask]selects all rows and only the non-duplicate columns.
Method 3: Drop Using df.drop() with a Custom Detection Function
Combine the duplicate detection function from earlier with DataFrame.drop() for a clear, explicit approach:
import pandas as pd
def get_duplicate_columns(df):
"""Return column names whose content duplicates an earlier column."""
duplicate_columns = set()
for i in range(df.shape[1]):
for j in range(i + 1, df.shape[1]):
if df.iloc[:, i].equals(df.iloc[:, j]):
duplicate_columns.add(df.columns[j])
return list(duplicate_columns)
students = [
("Michael", 34, "California", 34),
("Emily", 30, "Texas", 30),
("Jacob", 16, "Florida", 16),
("Emily", 30, "New York", 30),
("Olivia", 40, "Illinois", 40),
("Daniel", 30, "Washington", 30),
]
df = pd.DataFrame(students, columns=["Name", "Age", "Domicile", "Marks"])
duplicate_cols = get_duplicate_columns(df)
print(f"Dropping columns: {duplicate_cols}")
df_clean = df.drop(columns=duplicate_cols)
print(df_clean)Output:
Dropping columns: ['Marks']
Name Age Domicile
0 Michael 34 California
1 Emily 30 Texas
2 Jacob 16 Florida
3 Emily 30 New York
4 Olivia 40 Illinois
5 Daniel 30 WashingtonThis approach preserves the original data types and gives you full control over which columns are removed.
Method 4: Using Column Correlation for Near-Duplicates
Sometimes columns aren't exactly identical but are highly correlated (e.g., due to rounding differences). You can use correlation to detect near-duplicates:
import numpy as np
import pandas as pd
df_numeric = pd.DataFrame({
"A": [1.0, 2.0, 3.0, 4.0, 5.0],
"B": [10, 20, 30, 40, 50],
"C": [1.001, 2.001, 3.001, 4.001, 5.001], # Near-duplicate of A
})
corr_matrix = df_numeric.corr().abs()
upper_triangle = corr_matrix.where(
np.triu(np.ones(corr_matrix.shape), k=1).astype(bool)
)
threshold = 0.99
to_drop = [col for col in upper_triangle.columns if any(upper_triangle[col] > threshold)]
print(f"Near-duplicate columns to drop: {to_drop}")
df_clean = df_numeric.drop(columns=to_drop)
print(df_clean)Output:
Near-duplicate columns to drop: ['B', 'C']
A
0 1.0
1 2.0
2 3.0
3 4.0
4 5.0Common Mistake: Using inplace=True with Chained Operations
Dropping columns with inplace=True on a filtered DataFrame can lead to unexpected behavior:
duplicate_cols = df.columns[df.columns.duplicated()]
df.drop(columns=duplicate_cols, inplace=True)While this works in simple cases, chained operations with inplace=True can cause SettingWithCopyWarning. The safer approach is to assign the result to a new variable:
df_clean = df.drop(columns=duplicate_cols)Comparison of Methods
| Method | Detects Content Duplicates | Detects Name Duplicates | Preserves Dtypes | Performance |
|---|---|---|---|---|
Transpose + drop_duplicates() |
✅ | ✅ | ❌ (may change) | ⚠️ Slow for large data |
df.loc[:, ~duplicated()] |
❌ | ✅ | ✅ | ✅ Fast |
Custom function + df.drop() |
✅ | ✅ | ✅ | ⚠️ O(n²) columns |
| Correlation-based detection | ✅ (near-duplicates) | ❌ | ✅ | ✅ Fast (numeric only) |
Conclusion
Duplicate columns waste memory, cause confusion, and can lead to errors in analysis. Pandas provides several ways to find and remove them:
- For duplicate column names, use
df.loc[:, ~df.columns.duplicated()]- it's fast, simple, and preserves data types. - For duplicate column content (different names, same data), use a custom comparison function with
df.drop()for the most reliable results. - For a quick one-liner, transpose with
df.T.drop_duplicates().Tworks but may alter data types. - For near-duplicates in numeric data, correlation analysis with a threshold can catch columns that are almost identical.
Choose the method that matches your specific scenario - whether you're dealing with duplicate names from a merge operation or redundant data columns in a large dataset.