{"record":{"id":"f7eb784141c2e68d","repo":"pola-rs/polars","slug":"only-ufuncs-that-return-one-1d-array-are-supported","errorCode":null,"errorMessage":"only ufuncs that return one 1D array are supported","messagePattern":"only ufuncs that return one 1D array are supported","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/series/series.py","lineNumber":1518,"sourceCode":"                raise RuntimeError(msg)\n\n            arr = arr.__array__(dtype)\n\n        return arr\n\n    def __array_ufunc__(\n        self, ufunc: np.ufunc, method: str_, *inputs: Any, **kwargs: Any\n    ) -> Series:\n        \"\"\"Numpy universal functions.\"\"\"\n        if self._s.n_chunks() > 1:\n            self._s.rechunk(in_place=True)\n\n        s = self._s\n\n        if method == \"__call__\":\n            if ufunc.nout != 1:\n                msg = \"only ufuncs that return one 1D array are supported\"\n                raise NotImplementedError(msg)\n\n            args: list[int | float | np.ndarray[Any, Any]] = []\n            for arg in inputs:\n                if isinstance(arg, (int, float, np.ndarray)):\n                    args.append(arg)\n                elif isinstance(arg, Series):\n                    phys_arg = arg.to_physical()\n                    if phys_arg._s.n_chunks() > 1:\n                        phys_arg._s.rechunk(in_place=True)\n                    args.append(phys_arg._s.to_numpy_view())  # type: ignore[arg-type]\n                else:\n                    msg = f\"unsupported type {qualified_type_name(arg)!r} for {arg!r}\"\n                    raise TypeError(msg)\n\n            # Get minimum dtype needed to be able to cast all input arguments to the\n            # same dtype.\n            dtype_char_minimum: str = np.result_type(*args).char\n","sourceCodeStart":1500,"sourceCodeEnd":1536,"githubUrl":"https://github.com/pola-rs/polars/blob/fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e/py-polars/src/polars/series/series.py#L1500-L1536","documentation":"Series.__array_ufunc__ supports numpy ufuncs applied to a Series only when the ufunc produces exactly one output array (nout == 1). Multi-output ufuncs like np.modf or np.frexp are not supported, so NotImplementedError is raised at py-polars/src/polars/series/series.py:1518.","triggerScenarios":"`np.modf(series)`, `np.frexp(series)`, or any other ufunc with nout > 1 called on a Series, entering the `method == \"__call__\"` branch with `ufunc.nout != 1`.","commonSituations":"Using np.modf to split fractional/integer parts of a float Series; np.frexp for mantissa/exponent; generic numpy code paths that call arbitrary ufuncs on array-likes.","solutions":["Split the operation into single-output ufuncs: use `s % 1` and `s // 1` instead of np.modf","Compute via polars expressions: `pl.Series([np.modf(x)[0] for x in s.to_numpy()])` as a fallback on the numpy conversion","Wrap multi-output calls around `s.to_numpy()` so numpy sees a real ndarray, then reassemble Series from each output"],"exampleFix":"// before\nfrac, integral = np.modf(s)  # NotImplementedError\n// after\nfrac = s % 1\nintegral = s // 1","handlingStrategy":"fallback","validationCode":"if getattr(ufunc, \"nout\", 1) != 1:\n    arr = series.to_numpy()\n    outputs = ufunc(arr)  # run on ndarray instead\nelse:\n    result = ufunc(series)","typeGuard":"def is_single_output_ufunc(ufunc) -> bool:\n    return getattr(ufunc, \"nout\", 1) == 1","tryCatchPattern":"try:\n    result = np.modf(series)\nexcept NotImplementedError as e:\n    if \"one 1D array\" in str(e):\n        frac, integral = np.modf(series.to_numpy())\n        result = (pl.Series(frac), pl.Series(integral))\n    else:\n        raise","preventionTips":["Prefer polars expressions over multi-output numpy ufuncs","Call nout>1 ufuncs on series.to_numpy() explicitly","List supported ufuncs in interop layers and test with np.modf"],"tags":["polars","python","numpy","ufunc","not-implemented"],"backgroundTag":"operation-not-supported","analyzedSha":"fe841f959ef4d2ceefc05a310d33ed7b1ab24e5e","analyzedAt":"2026-09-18T22:14:11.667Z","contentChangedAt":"2026-09-18T22:14:11.667Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}