pandas-dev/pandas · error · NotImplementedError

can only perform ops with 1-d structures

Error message

can only perform ops with 1-d structures

What it means

Raised by BaseMaskedArray._arith_method when the 'other' operand is a list-like (ndarray or ExtensionArray) with more than one dimension. Masked array arithmetic is only defined element-wise against scalars or 1-D structures of matching length; 2-D inputs are rejected because broadcasting semantics are not implemented at this layer.

Solutions

  1. Reshape the operand to 1-D: other.ravel(), other.flatten(), or other[:, 0].
  2. Use a DataFrame to perform aligned 2-D operations instead of array-level arithmetic.
  3. Broadcast explicitly by iterating columns and combining results.

Example fix

// before
arr + matrix   # matrix.ndim == 2 -> raises
// after
arr + matrix[:, 0]   # 1-D operand
Defensive patterns

Strategy: validation

Validate before calling

import numpy as np
other_arr = np.asarray(other)
if other_arr.ndim > 1:
    other = other_arr.reshape(other_arr.shape[0])
result = arr + other

Type guard

def is_1d_or_scalar(other) -> bool:
    import numpy as np
    if np.isscalar(other):
        return True
    return hasattr(other, 'ndim') and other.ndim == 1

Try / catch

try:
    result = arr + other
except NotImplementedError as e:
    if '1-d structures' in str(e):
        result = arr + np.asarray(other).reshape(-1)
    else:
        raise

Prevention

When it happens

Trigger: Computing masked_array + two_dimensional_ndarray, or any binary op (+, -, *, /, comparison via _arith_method) where other.ndim > 1 after np.asarray conversion.

Common situations: Broadcasting a column against a matrix during feature engineering; passing a 2-D numpy array where a 1-D was expected; mis-shaped joins or concatenations feeding into arithmetic.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/18c27b85705bf09a. Report an issue: GitHub.

Appendix: source

Thrown at pandas/core/arrays/masked.py:984

            )

        if (
            not hasattr(other, "dtype")
            and is_list_like(other)
            and len(other) == len(self)
        ):
            # Try inferring masked dtype instead of casting to object
            other = pd_array(other)
            other = extract_array(other, extract_numpy=True)

        if isinstance(other, BaseMaskedArray):
            other, omask = other._data, other._mask

        elif is_list_like(other):
            if not isinstance(other, ExtensionArray):
                other = np.asarray(other)
            if other.ndim > 1:
                raise NotImplementedError("can only perform ops with 1-d structures")

        # We wrap the non-masked arithmetic logic used for numpy dtypes
        #  in Series/Index arithmetic ops.
        other = ops.maybe_prepare_scalar_for_op(other, (len(self),))
        pd_op = ops.get_array_op(op)
        other = ensure_wrapped_if_datetimelike(other)

        if isinstance(other, ExtensionArray) and isinstance(other.dtype, ArrowDtype):
            # GH#58602
            return NotImplemented

        if op_name in {"pow", "rpow"} and isinstance(other, np.bool_):
            # Avoid DeprecationWarning: In future, it will be an error
            #  for 'np.bool_' scalars to be interpreted as an index
            #  e.g. test_array_scalar_like_equivalence
            other = bool(other)

        mask = self._propagate_mask(omask, other)

View on GitHub (pinned to 3b7651241d)