pandas-dev/pandas · error · NotImplementedError

contains not implemented for two intervals

Error message

contains not implemented for two intervals

What it means

Raised by IntervalArray.contains when 'other' is itself a pd.Interval. The vectorized contains check is defined for scalar points only; interval-vs-interval containment is not implemented and the code explicitly refuses rather than returning a misleading result.

Source

Thrown at pandas/core/arrays/interval.py:1829

        See Also
        --------
        Interval.contains : Check whether Interval object contains value.
        IntervalArray.overlaps : Check if an Interval overlaps the values in the
            IntervalArray.

        Examples
        --------
        >>> intervals = pd.arrays.IntervalArray.from_tuples([(0, 1), (1, 3), (2, 4)])
        >>> intervals
        <IntervalArray>
        [(0, 1], (1, 3], (2, 4]]
        Length: 3, dtype: interval[int64, right]

        >>> intervals.contains(0.5)
        array([ True, False, False])
        """
        if isinstance(other, Interval):
            raise NotImplementedError("contains not implemented for two intervals")

        return (self._left < other if self.open_left else self._left <= other) & (
            other < self._right if self.open_right else other <= self._right
        )

    def isin(self, values: ArrayLike) -> npt.NDArray[np.bool_]:
        if isinstance(values, IntervalArray):
            if self.closed != values.closed:
                # not comparable -> no overlap
                return np.zeros(self.shape, dtype=bool)

            if self.dtype == values.dtype:
                left = self._combined
                right = values._combined
                return np.isin(left, right).ravel()

            elif needs_i8_conversion(self.left.dtype) ^ needs_i8_conversion(
                values.left.dtype

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Use arr.overlaps(other_interval) for overlap semantics, or compute containment manually via (arr.left <= other.left) & (arr.right >= other.right).
  2. If checking whether a single point lies in any interval, pass the scalar directly: arr.contains(0.5).
  3. Loop point-by-point if you truly need interval containment per element.

Example fix

# before
arr.contains(pd.Interval(0, 1))

# after
(arr.left <= 0) & (arr.right >= 1)
Defensive patterns

Strategy: type-guard

Validate before calling

def contains_arg(value):
    if isinstance(value, pd.Interval):
        raise TypeError('use overlaps or manual containment, not contains')
    return value

Type guard

def is_not_interval(value) -> bool:
    return not isinstance(value, pd.Interval)

Prevention

When it happens

Trigger: Calling arr.contains(pd.Interval(0, 1)) instead of arr.contains(0.5).

Common situations: Users reaching for contains expecting it to behave like overlaps; library code that pipes interval filters through contains.

Related errors


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