Skip to content

IndexingError: Unalignable boolean Series provided as indexer

Have you built a perfectly good boolean mask and had Pandas refuse to use it?

sales = pd.DataFrame({'region': ['North', 'South', 'North'],
                      'revenue': [100, 250, 175]})

sales[pd.Series([True, False, True], index=[7, 8, 9])]
IndexingError: Unalignable boolean Series provided as indexer (index of the boolean Series and of the indexed object do not match).

Three values, three rows, and Pandas still says no. The reason is that a boolean Series is matched by label, not by position. The mask is labeled 7, 8, 9; the frame is labeled 0, 1, 2; nothing lines up, so there is no honest answer.

If the positions really are what you mean, strip the labels:

sales[pd.Series([True, False, True], index=[7, 8, 9]).values]
  region  revenue
0  North      100
2  North      175

Where the mismatched index comes from

You rarely type an index like that. It arrives because the mask was computed from a frame that had already been filtered, sorted or sampled:

recent = sales.tail(2)                    # index 1, 2
sales[recent['revenue'] > 100]            # raises

tail kept the original labels, so the mask covers only part of the frame you are applying it to. The fix is not to force it through with .values — that would silently apply a two-value mask to a three-row frame at the wrong offsets. The fix is to build the mask from the frame you are indexing:

sales[sales['revenue'] > 100]

When you genuinely need a condition computed elsewhere, reindex makes the alignment explicit and fills the gaps:

mask = (recent['revenue'] > 100).reindex(sales.index, fill_value=False)
sales[mask]

Now every row has an answer, and the rows the mask never covered are excluded on purpose rather than by accident.

Why alignment is worth the inconvenience

The same behavior that raises here is what makes Pandas trustworthy elsewhere. Adding two Series lines them up by label, so you cannot accidentally add January's sales to February's just because they happen to sit in the same position. Boolean indexing follows the same rule, and refusing to guess is the consistent version of that promise.

.values opts out of it. That is occasionally right — a mask from NumPy, or one you built positionally on purpose — and it is worth a comment in the code saying which.

The mistakes I see most often

Reaching for .values to make the error go away. It converts a loud failure into a silent misalignment, which is strictly worse.

Forgetting reset_index(drop=True) after filtering. If you filter and then work positionally from there, resetting the index once removes a whole family of these.

Confusing this with the non-boolean mask error. If the message mentions NA or NaN values instead, the problem is missing values in the mask, not its index.

Practice

See loc in Pandas for label-based selection, iloc in Pandas for position-based selection, and reset_index in Pandas for realigning after a filter.