pandas-dev/pandas · error · NotImplementedError

Cannot apply ufunc {ufunc} to mixed DataFrame and Series inp

Error message

Cannot apply ufunc {ufunc} to mixed DataFrame and Series inputs.

What it means

Raised by NDFrame.__array_ufunc__ in arraylike.py:336 as a NotImplementedError when a numpy ufunc is called with a mix of DataFrame and Series inputs (e.g. np.add(df, series)). Pandas currently only auto-aligns pairs of the same NDFrame kind; a mixed DataFrame+Series pair would need ambiguous axis alignment that isn't implemented, so it is rejected rather than silently producing a wrong result.

Source

Thrown at pandas/core/arraylike.py:336

            return NotImplemented

    # align all the inputs.
    types = tuple(type(x) for x in inputs)
    alignable = [
        x for x, t in zip(inputs, types, strict=True) if issubclass(t, NDFrame)
    ]

    if len(alignable) > 1:
        # This triggers alignment.
        # At the moment, there aren't any ufuncs with more than two inputs
        # so this ends up just being x1.index | x2.index, but we write
        # it to handle *args.
        set_types = set(types)
        if len(set_types) > 1 and {DataFrame, Series}.issubset(set_types):
            # We currently don't handle ufunc(DataFrame, Series)
            # well. Previously this raised an internal ValueError. We might
            # support it someday, so raise a NotImplementedError.
            raise NotImplementedError(
                f"Cannot apply ufunc {ufunc} to mixed DataFrame and Series inputs."
            )
        axes = self.axes
        for obj in alignable[1:]:
            # this relies on the fact that we aren't handling mixed
            # series / frame ufuncs.
            for i, (ax1, ax2) in enumerate(zip(axes, obj.axes, strict=True)):
                axes[i] = ax1.union(ax2)

        reconstruct_axes = dict(zip(self._AXIS_ORDERS, axes, strict=True))
        inputs = tuple(
            x.reindex(**reconstruct_axes) if issubclass(t, NDFrame) else x
            for x, t in zip(inputs, types, strict=True)
        )
    else:
        reconstruct_axes = dict(zip(self._AXIS_ORDERS, self.axes, strict=True))

    if self.ndim == 1:

View on GitHub (pinned to 71959b8cb9)

Solutions

  1. Align types: convert the Series to a DataFrame with matching shape (e.g. s.to_frame().T) or extract a numpy array from one input.
  2. Use pandas arithmetic operators which handle alignment: df + s (with axis=) or df.add(s, axis=...).
  3. Pull the underlying ndarray if alignment isn't needed: np.add(df.values, s.values) (be explicit about shapes).

Example fix

// before
np.add(df, s)  # mixed DataFrame + Series
// after
df.add(s, axis=1)  # pandas operator handles alignment
// or
np.add(df.values, s.values)
Defensive patterns

Strategy: type-guard

Validate before calling

import pandas as pd
types = {type(x) for x in inputs}
if pd.DataFrame in types and pd.Series in types:
    raise NotImplementedError('numpy ufunc cannot mix DataFrame and Series inputs; align types first')

Type guard

def ufunc_inputs_homogeneous(inputs) -> bool:
    import pandas as pd
    types = {type(x) for x in inputs}
    return not ({pd.DataFrame, pd.Series} <= types)

Try / catch

try:
    np.ufunc(df, series)
except NotImplementedError as e:
    if 'mixed DataFrame and Series' in str(e):
        df.add(series, axis=1)  # use pandas op with alignment
    else:
        raise

Prevention

When it happens

Trigger: np.add(df, s), np.multiply(s, df), or any numpy ufunc where one positional input is a DataFrame and another is a Series. Hit at arraylike.py:326-338 when len(alignable) > 1 and both DataFrame and Series are present in the input type set.

Common situations: Passing a row Series (e.g. df.iloc[0]) to a ufunc expecting a scalar per column; mixing a frame and a derived Series in vectorized math; assuming numpy broadcasts a Series across a DataFrame like it does across a 2-D ndarray.

Related errors


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