Home › Python

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all(). — how to fix

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Quick fix: In filters use &, |, ~ with parentheses instead of and, or, not: df[(df.a > 1) & (df.b < 5)]. In if statements reduce to one value: if (df.a > 1).any(): or .all(), if df.empty:. For row-wise logic use np.where or .apply, not if.

What it means

A comparison like df["age"] > 30 returns a Series of booleans, one per row. Python's and, or, not, if and while call bool() on their operand, and pandas refuses to guess whether a Series of many values is "true" (any row? all rows? non-empty?). So it raises this error and lists the ways to say what you mean.

Cause 1: and / or in a filter

# Wrong
df[df["age"] > 30 and df["city"] == "Paris"]

# Right: element-wise operators, each condition in parentheses
df[(df["age"] > 30) & (df["city"] == "Paris")]
df[(df["age"] > 30) | (df["vip"] == True)]
df[~(df["status"] == "closed")]

The parentheses are required: & and | bind tighter than > and ==, so df.a > 1 & df.b < 5 is parsed wrongly and also raises this error.

df.query("age > 30 and city == 'Paris'") is an alternative where and/or are allowed.

Cause 2: if on a Series

# Wrong
if df["score"] > 50:
    ...

# Decide what you mean
if (df["score"] > 50).any():   # at least one row
    ...
if (df["score"] > 50).all():   # every row
    ...
if df.empty:                   # no rows at all
    ...

If you expect exactly one row, use .item(), which raises if there isn't exactly one element:

if (df.loc[df.id == 7, "score"] > 50).item():
    ...

Cause 3: row-by-row logic written as an if

Writing a function with if and passing whole columns doesn't work:

def grade(score):
    if score > 50:          # score is a Series here -> error
        return "pass"
    return "fail"

df["grade"] = grade(df["score"])

Vectorise it:

import numpy as np
df["grade"] = np.where(df["score"] > 50, "pass", "fail")

# several conditions
df["band"] = np.select(
    [df.score >= 80, df.score >= 50],
    ["high", "mid"],
    default="low",
)

Or apply the function per value (slower, but fine for small data): df["grade"] = df["score"].apply(grade).

Cause 4: in, == or bool() on a Series

Cause 5: NumPy arrays

The NumPy version (truth value of an array with more than one element is ambiguous) has the same fixes: np.logical_and(a > 1, b < 5) or (a > 1) & (b < 5), and .any() / .all() in conditions.

Note: Series.bool() mentioned in the message is deprecated since pandas 2.1; use .item() instead.

Last updated 2026-11-01.