diff --git a/pandas/core/arrays/arrow/array.py b/pandas/core/arrays/arrow/array.py index e2a74ea6f5351..aafd4cbeeaedf 100644 --- a/pandas/core/arrays/arrow/array.py +++ b/pandas/core/arrays/arrow/array.py @@ -985,7 +985,18 @@ def _accumulate( pyarrow_meth = getattr(pc, pyarrow_name, None) if pyarrow_meth is None: return super()._accumulate(name, skipna=skipna, **kwargs) - result = pyarrow_meth(self._data, skip_nulls=skipna, **kwargs) + + data_to_accum = self._data + + pa_dtype = data_to_accum.type + if pa.types.is_duration(pa_dtype): + data_to_accum = data_to_accum.cast(pa.int64()) + + result = pyarrow_meth(data_to_accum, skip_nulls=skipna, **kwargs) + + if pa.types.is_duration(pa_dtype): + result = result.cast(pa_dtype) + return type(self)(result) def _reduce(self, name: str, *, skipna: bool = True, **kwargs): diff --git a/pandas/tests/extension/test_arrow.py b/pandas/tests/extension/test_arrow.py index a7c243cdfe74f..b453503467662 100644 --- a/pandas/tests/extension/test_arrow.py +++ b/pandas/tests/extension/test_arrow.py @@ -372,16 +372,27 @@ def test_getitem_scalar(self, data): class TestBaseAccumulateTests(base.BaseAccumulateTests): - def check_accumulate(self, s, op_name, skipna): - result = getattr(s, op_name)(skipna=skipna).astype("Float64") - expected = getattr(s.astype("Float64"), op_name)(skipna=skipna) + def check_accumulate(self, ser, op_name, skipna): + result = getattr(ser, op_name)(skipna=skipna) + + if ser.dtype.kind == "m": + # Just check that we match the integer behavior. + ser = ser.astype("int64[pyarrow]") + result = result.astype("int64[pyarrow]") + + result = result.astype("Float64") + expected = getattr(ser.astype("Float64"), op_name)(skipna=skipna) self.assert_series_equal(result, expected, check_dtype=False) @pytest.mark.parametrize("skipna", [True, False]) def test_accumulate_series_raises(self, data, all_numeric_accumulations, skipna): pa_type = data.dtype.pyarrow_dtype if ( - (pa.types.is_integer(pa_type) or pa.types.is_floating(pa_type)) + ( + pa.types.is_integer(pa_type) + or pa.types.is_floating(pa_type) + or pa.types.is_duration(pa_type) + ) and all_numeric_accumulations == "cumsum" and not pa_version_under9p0 ): @@ -423,9 +434,7 @@ def test_accumulate_series(self, data, all_numeric_accumulations, skipna, reques raises=NotImplementedError, ) ) - elif all_numeric_accumulations == "cumsum" and ( - pa.types.is_duration(pa_type) or pa.types.is_boolean(pa_type) - ): + elif all_numeric_accumulations == "cumsum" and (pa.types.is_boolean(pa_type)): request.node.add_marker( pytest.mark.xfail( reason=f"{all_numeric_accumulations} not implemented for {pa_type}",