pandas-dev/pandas · error · TypeError

Cannot compare types {!r} and {!r}

Error message

Cannot compare types {!r} and {!r}

What it means

Raised by _check_comparison_types inside compare_or_regex_search (replace.py:81) as a TypeError when a DataFrame/Series.replace operation tries to compare values of incompatible types and the comparison returns a scalar bool rather than an elementwise array. The check fires when the elementwise equality between the array and the replacement target collapses to a single Python bool - an indication the types cannot be meaningfully compared (e.g. comparing a string column to a number).

Source

Thrown at pandas/core/array_algos/replace.py:81

    -------
    mask : array-like of bool
    """
    if isna(b):
        return ~mask

    def _check_comparison_types(
        result: ArrayLike | bool, a: ArrayLike, b: Scalar | Pattern
    ) -> None:
        """
        Raises an error if the two arrays (a,b) cannot be compared.
        Otherwise, returns the comparison result as expected.
        """
        if is_bool(result) and isinstance(a, np.ndarray):
            type_names = [type(a).__name__, type(b).__name__]

            type_names[0] = f"ndarray(dtype={a.dtype})"

            raise TypeError(
                f"Cannot compare types {type_names[0]!r} and {type_names[1]!r}"
            )

    if not regex or not should_use_regex(regex, b):
        # TODO: should use missing.mask_missing?
        op = lambda x: operator.eq(x, b)
    else:
        op = np.vectorize(
            lambda x: (
                bool(re.search(b, x))
                if isinstance(x, str) and isinstance(b, (str, Pattern))
                else False
            ),
            otypes=[bool],
        )

    # GH#32621 use mask to avoid comparing to NAs
    if isinstance(a, np.ndarray) and mask is not None:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Ensure to_replace and the target column share a comparable type (e.g. replace ints with ints, strings with strings).
  2. Cast the column to the matching dtype first: df['col'] = df['col'].astype(str) before df.replace('x', 'y').
  3. Target the specific column explicitly: df['col'].replace(old, new) so types line up.
  4. If you intended a cross-type replacement, do an explicit astype after the logical replacement rather than asking replace to compare incompatible types.

Example fix

// before
df = pd.DataFrame({'a': [1,2,3]})
df.replace('x', 0)  # str vs int column
// after
df['a'] = df['a'].astype(str)
df.replace('x', '0')
Defensive patterns

Strategy: validation

Validate before calling

from pandas.api.types import infer_dtype
for col in df.columns:
    inferred = infer_dtype(df[col], skipna=True)
    if inferred not in ('string','bytes','empty') and isinstance(to_replace, str):
        raise TypeError(f'cannot compare str to_replace to {col} ({inferred})')

Type guard

def replace_types_comparable(df, to_replace) -> bool:
    from pandas.api.types import infer_dtype
    target_kind = type(to_replace).__name__
    for col in df.columns:
        inferred = infer_dtype(df[col], skipna=True)
        numeric_kinds = {'integer','floating','mixed-integer-float'}
        if isinstance(to_replace, str) and inferred in numeric_kinds:
            return False
        if isinstance(to_replace, (int, float)) and inferred in {'string'}:
            return False
    return True

Try / catch

try:
    df.replace(to_replace, value)
except TypeError as e:
    if 'Cannot compare types' in str(e):
        df = df.astype(str)
        df.replace(str(to_replace), str(value))
    else:
        raise

Prevention

When it happens

Trigger: df.replace(to_replace=..., value=...) where to_replace is a value whose type cannot be compared to the column dtype, e.g. df.replace('x', 0) on a numeric column, or replacing a string in an int column with regex=False. Hit at replace.py:76-83 inside compare_or_regex_search when is_bool(result) and isinstance(a, np.ndarray).

Common situations: Calling replace with a to_replace value whose type doesn't match the column dtype; numeric column with a string pattern; replacing across mixed-type columns in one call; building replacement dicts dynamically with mismatched value types.

Related errors


AI-assisted analysis of pandas-dev/pandas@71959b8cb9 (2026-08-07). Data as JSON: /api/errors/2b80f54c5a6e5479. Report an issue: GitHub.