How to Resolve "ValueError: Can only compare identically-labeled Series objects" in Python
When working with Pandas, you may encounter the error ValueError: Can only compare identically-labeled Series objects. This happens when you try to compare two Series (or DataFrame columns) that have different index labels. Pandas aligns data by index during comparisons, and if the labels don't match, it raises this error instead of guessing how to align them.
In this guide, we'll explain why this happens and show you multiple ways to fix it depending on what kind of comparison you actually need.
Why Does This Error Occur?
Pandas uses index-based alignment for all operations, including comparisons. When you use == between two Series, Pandas tries to match elements by their index labels, not by their position. If the indexes don't match exactly, Pandas can't determine how to align the data and raises a ValueError.
❌ Example that triggers the error:
import pandas as pd
s1 = pd.Series([10, 20, 30], index=[0, 1, 2])
s2 = pd.Series([10, 20, 30], index=[2, 1, 0])
print(s1 == s2)
Output:
ValueError: Can only compare identically-labeled Series objects
Even though both Series contain the same values (10, 20, 30), their index labels are in different order. Pandas won't assume you want positional comparison: it insists on label alignment.
This error can also occur with !=, <, >, <=, >=, and when comparing DataFrame columns with mismatched indexes.
Understanding the Core Issue
Let's visualize what Pandas sees:
s1: s2:
index value index value
0 → 10 2 → 10
1 → 20 1 → 20
2 → 30 0 → 30
When comparing s1 == s2, Pandas tries to align by index:
- Index
0: s1 has10, s2 has30→ Not aligned the way you might expect - But the indexes don't even fully match in order → Error
The fix depends on what you're trying to compare: values only, values with labels, or values at the same positions.
Solutions
Solution 1: Compare Values Only with .values
If you only care about whether the underlying data arrays are identical (ignoring indexes completely), compare the .values arrays:
import pandas as pd
import numpy as np
s1 = pd.Series([10, 20, 30], index=[0, 1, 2])
s2 = pd.Series([10, 20, 30], index=[2, 1, 0])
# Compare raw values (as NumPy arrays)
result = np.array_equal(s1.values, s2.values)
print(result)
Output:
True
Both Series contain [10, 20, 30] in the same order, so the comparison returns True.
For element-wise comparison (returning a boolean array):
import pandas as pd
import numpy as np
s1 = pd.Series([10, 20, 30], index=[0, 1, 2])
s2 = pd.Series([10, 20, 30], index=[2, 1, 0])
result = s1.values == s2.values
print(result)
Output:
[ True True True]
Use .values comparison when:
- The index is meaningless (e.g., auto-generated row numbers)
- You want to compare data in the exact positional order it appears
- You're dealing with DataFrames from different sources with arbitrary indexes
Solution 2: Reset the Index with reset_index(drop=True)
If you want the result as a Pandas Series (preserving the Series format) but want to ignore the original indexes, reset both indexes first:
import pandas as pd
s1 = pd.Series([10, 20, 30], index=[0, 1, 2])
s2 = pd.Series([10, 20, 30], index=[2, 1, 0])
result = s1.reset_index(drop=True) == s2.reset_index(drop=True)
print(result)
Output:
0 True
1 True
2 True
dtype: bool
The drop=True parameter prevents the old index from being added as a column. Both Series now have a fresh 0, 1, 2 index, so positional comparison works.
Solution 3: Sort the Index with sort_index()
If both Series have the same index labels but in a different order, sorting both indexes aligns them correctly:
import pandas as pd
s1 = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
s2 = pd.Series([30, 20, 10], index=['c', 'b', 'a'])
result = s1.sort_index() == s2.sort_index()
print(result)
Output:
a True
b True
c True
dtype: bool
After sorting, both Series have the index order [a, b, c]:
s1sorted:a→10, b→20, c→30s2sorted:a→10, b→20, c→30
They match perfectly.
sort_index() only works when both Series have the same set of index labels. If one Series has labels that the other doesn't, you'll still get an error or NaN values.
Solution 4: Use .equals() for Full Equality Check
The .equals() method checks whether two Series are completely identical, i.e. both the data and the index:
import pandas as pd
s1 = pd.Series([10, 20, 30], index=[0, 1, 2])
s2 = pd.Series([10, 20, 30], index=[2, 1, 0])
# Checks both values AND index
print(s1.equals(s2)) # False: indexes differ
s3 = pd.Series([10, 20, 30], index=[0, 1, 2])
print(s1.equals(s3)) # True: both match
Output:
False
True
.equals() never raises an error: it simply returns True or False. It also handles NaN values correctly (considering NaN == NaN as True).
Solution 5: Use .align() for Explicit Index Alignment
If you want to see how the data aligns before comparing, use .align():
import pandas as pd
s1 = pd.Series([10, 20, 30], index=['a', 'b', 'c'])
s2 = pd.Series([100, 200], index=['b', 'd'])
# Align with outer join: fills missing values with NaN
aligned_s1, aligned_s2 = s1.align(s2, join='outer')
print("Aligned s1:")
print(aligned_s1)
print("\nAligned s2:")
print(aligned_s2)
# Now comparison works
print("\nComparison:")
print(aligned_s1 == aligned_s2)
Output:
Aligned s1:
a 10.0
b 20.0
c 30.0
d NaN
dtype: float64
Aligned s2:
a NaN
b 100.0
c NaN
d 200.0
dtype: float64
Comparison:
a False
b False
c False
d False
dtype: bool
The join parameter controls how missing labels are handled:
| Join Type | Behavior |
|---|---|
'outer' | Include all labels from both Series (fill with NaN) |
'inner' | Include only labels present in both Series |
'left' | Use labels from the left Series only |
'right' | Use labels from the right Series only |
Practical Example: Comparing DataFrame Columns
This error frequently appears when comparing columns from different DataFrames:
❌ Wrong:
import pandas as pd
df1 = pd.DataFrame({'score': [85, 90, 78]}, index=['Alice', 'Bob', 'Carol'])
df2 = pd.DataFrame({'score': [85, 90, 78]}, index=['Bob', 'Carol', 'Alice'])
result = df1['score'] == df2['score']
# ValueError: Can only compare identically-labeled Series objects
✅ Fix: Sort both indexes first:
import pandas as pd
df1 = pd.DataFrame({'score': [85, 90, 78]}, index=['Alice', 'Bob', 'Carol'])
df2 = pd.DataFrame({'score': [85, 90, 78]}, index=['Bob', 'Carol', 'Alice'])
result = df1['score'].sort_index() == df2['score'].sort_index()
print(result)
Output:
Alice True
Bob True
Carol True
Name: score, dtype: bool
✅ Or compare values only:
import pandas as pd
import numpy as np
df1 = pd.DataFrame({'score': [85, 90, 78]},index=['Alice', 'Bob', 'Carol'])
df2 = pd.DataFrame({'score': [85, 90, 78]}, index=['Bob', 'Carol', 'Alice'])
# Compare positionally (ignoring index labels)
result = np.array_equal(df1['score'].values, df2['score'].values)
print("df1 values:", df1['score'].values)
print("df2 values:", df2['score'].values)
print("Positionally equal?", result)
Output:
df1 values: [85 90 78]
df2 values: [85 90 78]
Positionally equal? True
Choosing the Right Solution
| What You Want to Compare | Method | Handles Mismatched Indexes? |
|---|---|---|
| Are the raw values identical (positionally)? | np.array_equal(s1.values, s2.values) | ✅ Yes (ignores index) |
| Element-wise comparison by position | s1.reset_index(drop=True) == s2.reset_index(drop=True) | ✅ Yes (resets index) |
| Element-wise comparison by label | s1.sort_index() == s2.sort_index() | ⚠️ Only if same labels exist |
| Complete equality (values + index) | s1.equals(s2) | ✅ Yes (returns True/False) |
| Comparison with explicit alignment control | s1.align(s2, join='...') then compare | ✅ Yes (handles missing labels) |
Conclusion
The ValueError: Can only compare identically-labeled Series objects error occurs because Pandas aligns data by index labels during comparisons, and mismatched indexes create an ambiguity it won't resolve automatically.
The fix depends on your intent: use .values or reset_index(drop=True) to compare data by position, sort_index() to align matching labels, .equals() for a complete equality check, or .align() when you need explicit control over how missing labels are handled.
Understanding whether you're comparing by position or by label is the key to choosing the right approach.