Skip to content

Commit 3b671c8

Browse files
Backport PR #39971: REGR: Fix assignment bug for unary operators (#39990)
Co-authored-by: Daniel Saxton <[email protected]>
1 parent 1325351 commit 3b671c8

File tree

4 files changed

+17
-3
lines changed

4 files changed

+17
-3
lines changed

doc/source/whatsnew/v1.2.3.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Fixed regressions
1616
~~~~~~~~~~~~~~~~~
1717

1818
- Fixed regression in :meth:`~DataFrame.to_excel` raising ``KeyError`` when giving duplicate columns with ``columns`` attribute (:issue:`39695`)
19+
- Fixed regression in :class:`IntegerArray` unary ops propagating mask on assignment (:issue:`39943`)
1920
- Fixed regression in :meth:`DataFrame.__setitem__` not aligning :class:`DataFrame` on right-hand side for boolean indexer (:issue:`39931`)
2021

2122
.. ---------------------------------------------------------------------------

pandas/core/arrays/integer.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -348,13 +348,13 @@ def __init__(self, values: np.ndarray, mask: np.ndarray, copy: bool = False):
348348
super().__init__(values, mask, copy=copy)
349349

350350
def __neg__(self):
351-
return type(self)(-self._data, self._mask)
351+
return type(self)(-self._data, self._mask.copy())
352352

353353
def __pos__(self):
354354
return self
355355

356356
def __abs__(self):
357-
return type(self)(np.abs(self._data), self._mask)
357+
return type(self)(np.abs(self._data), self._mask.copy())
358358

359359
@classmethod
360360
def _from_sequence(

pandas/core/arrays/masked.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ def __len__(self) -> int:
142142
return len(self._data)
143143

144144
def __invert__(self: BaseMaskedArrayT) -> BaseMaskedArrayT:
145-
return type(self)(~self._data, self._mask)
145+
return type(self)(~self._data, self._mask.copy())
146146

147147
def to_numpy(
148148
self, dtype=None, copy: bool = False, na_value: Scalar = lib.no_default

pandas/tests/arrays/masked/test_arithmetic.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,16 @@ def test_error_len_mismatch(data, all_arithmetic_operators):
159159
s = pd.Series(data)
160160
with pytest.raises(ValueError, match="Lengths must match"):
161161
op(s, other)
162+
163+
164+
@pytest.mark.parametrize("op", ["__neg__", "__abs__", "__invert__"])
165+
@pytest.mark.parametrize(
166+
"values, dtype", [([1, 2, 3], "Int64"), ([True, False, True], "boolean")]
167+
)
168+
def test_unary_op_does_not_propagate_mask(op, values, dtype):
169+
# https://github.com/pandas-dev/pandas/issues/39943
170+
s = pd.Series(values, dtype=dtype)
171+
result = getattr(s, op)()
172+
expected = result.copy(deep=True)
173+
s[0] = None
174+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)