diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index c74bcb505b6be..5976ecb6bffd3 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1349,6 +1349,7 @@ Indexing - Bug where setting a timedelta column by ``Index`` causes it to be casted to double, and therefore lose precision (:issue:`23511`) - Bug in :func:`Index.union` and :func:`Index.intersection` where name of the ``Index`` of the result was not computed correctly for certain cases (:issue:`9943`, :issue:`9862`) - Bug in :class:`Index` slicing with boolean :class:`Index` may raise ``TypeError`` (:issue:`22533`) +- Bug in ``PeriodArray.__setitem__`` when accepting slice and list-like value (:issue:`23978`) Missing ^^^^^^^ diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 53629dca4d391..dd79c9bddac15 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -347,7 +347,7 @@ def __repr__(self): def __setitem__( self, - key, # type: Union[int, Sequence[int], Sequence[bool]] + key, # type: Union[int, Sequence[int], Sequence[bool], slice] value # type: Union[NaTType, Period, Sequence[Period]] ): # type: (...) -> None @@ -357,11 +357,14 @@ def __setitem__( # ndarray[datetime64ns]. I think ndarray[int] / ndarray[str] won't # work, since the freq can't be inferred. if is_list_like(value): - if len(key) != len(value) and not com.is_bool_indexer(key): + is_slice = isinstance(key, slice) + if (not is_slice + and len(key) != len(value) + and not com.is_bool_indexer(key)): msg = ("shape mismatch: value array of length '{}' does not " "match indexing result of length '{}'.") raise ValueError(msg.format(len(key), len(value))) - if len(key) == 0: + if not is_slice and len(key) == 0: return value = period_array(value) diff --git a/pandas/tests/extension/base/setitem.py b/pandas/tests/extension/base/setitem.py index 3d798b2af5c43..479ab71676315 100644 --- a/pandas/tests/extension/base/setitem.py +++ b/pandas/tests/extension/base/setitem.py @@ -173,3 +173,13 @@ def test_setitem_tuple_index(self, data): expected = pd.Series(data.take([1, 1]), index=s.index) s[(0, 1)] = data[1] self.assert_series_equal(s, expected) + + def test_setitem_slice_mismatch_length_raises(self, data): + arr = data[:5] + with pytest.raises(ValueError): + arr[:1] = arr[:2] + + def test_setitem_slice_array(self, data): + arr = data[:5].copy() + arr[:5] = data[-5:] + self.assert_extension_array_equal(arr, data[-5:])