From 24e1b2b93ea499c229da3c7972257e4e812e9eef Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 29 Oct 2025 11:28:28 -0700 Subject: [PATCH 1/2] BUG: retain NAs in ufunc on ArrowEA --- pandas/core/arrays/arrow/array.py | 5 +++++ pandas/tests/extension/test_arrow.py | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index 08f1ffdcc6a0d..46f582b235e29 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -829,6 +829,11 @@ def __arrow_array__(self, type=None): """Convert myself to a pyarrow ChunkedArray.""" return self._pa_array + def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs): + # Need to wrap np.array results GH#62800 + result = super().__array_ufunc__(ufunc, method, *inputs, **kwargs) + return type(self)._from_sequence(result) + def __array__( self, dtype: NpDtype | None = None, copy: bool | None = None ) -> np.ndarray: diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index 2aa1b658fdf7b..c1e01bbbe57a0 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -3800,3 +3800,13 @@ def test_cast_pontwise_result_decimal_nan(): pa_type = result.dtype.pyarrow_dtype assert pa.types.is_decimal(pa_type) + + +def test_ufunc_retains_missing(): + # GH#62800 + ser = pd.Series([0.1, pd.NA], dtype="float64[pyarrow]") + + result = np.sin(ser) + + expected = pd.Series([np.sin(0.1), pd.NA], dtype="float64[pyarrow]") + tm.assert_series_equal(result, expected) From f180bc8ca0325d1b337ad1477c4faab07b2e15c6 Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 29 Oct 2025 14:01:07 -0700 Subject: [PATCH 2/2] Fix broken ArrowStringArray tests --- pandas/core/arrays/arrow/array.py | 5 ++++- pandas/tests/series/test_npfuncs.py | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index 46f582b235e29..53c938faf9257 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -832,7 +832,10 @@ def __arrow_array__(self, type=None): def __array_ufunc__(self, ufunc: np.ufunc, method: str, *inputs, **kwargs): # Need to wrap np.array results GH#62800 result = super().__array_ufunc__(ufunc, method, *inputs, **kwargs) - return type(self)._from_sequence(result) + if type(self) is ArrowExtensionArray: + # Exclude ArrowStringArray + return type(self)._from_sequence(result) + return result def __array__( self, dtype: NpDtype | None = None, copy: bool | None = None diff --git a/pandas/tests/series/test_npfuncs.py b/pandas/tests/series/test_npfuncs.py index b72ac8efbaa6d..f30c01b496399 100644 --- a/pandas/tests/series/test_npfuncs.py +++ b/pandas/tests/series/test_npfuncs.py @@ -43,7 +43,7 @@ def test_log_arrow_backed_missing_value(using_nan_is_na): ser = Series([1, 2, None], dtype="float64[pyarrow]") if using_nan_is_na: result = np.log(ser) - expected = np.log(Series([1, 2, None], dtype="float64")) + expected = np.log(Series([1, 2, None], dtype="float64[pyarrow]")) tm.assert_series_equal(result, expected) else: # we get cast to object which raises