From 3032ae7adf57bbc5d6e3fdcefa85c0ddb799945f Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 29 Oct 2020 22:58:52 +0100 Subject: [PATCH 1/6] REGR: revert behaviour of getitem with assigning with a Series --- pandas/core/series.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 379c4ac1c9526..317db60641132 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1048,10 +1048,8 @@ def _set_with_engine(self, key, value): def _set_with(self, key, value): # other: fancy integer or otherwise if isinstance(key, slice): - # extract_array so that if we set e.g. ser[-5:] = ser[:5] - # we get the first five values, and not 5 NaNs indexer = self.index._convert_slice_indexer(key, kind="getitem") - self.iloc[indexer] = extract_array(value, extract_numpy=True) + return self._set_values(indexer, value) else: assert not isinstance(key, tuple) @@ -1069,12 +1067,26 @@ def _set_with(self, key, value): # should be caught by the is_bool_indexer check in __setitem__ if key_type == "integer": if not self.index._should_fallback_to_positional(): - self.loc[key] = value + self._set_labels(key, value) else: - self.iloc[key] = value + self._set_values(key, value) else: self.loc[key] = value + def _set_labels(self, key, value): + key = com.asarray_tuplesafe(key) + indexer: np.ndarray = self.index.get_indexer(key) + mask = indexer == -1 + if mask.any(): + raise ValueError(f"{key[mask]} not contained in the index") + self._set_values(indexer, value) + + def _set_values(self, key, value): + if isinstance(key, Series): + key = key._values + self._mgr = self._mgr.setitem(indexer=key, value=value) + self._maybe_update_cacher() + def _set_value(self, label, value, takeable: bool = False): """ Quickly set single value at passed label. From 19c799fb8a5aef3766fd3c1ac0015abba3d2e30a Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 29 Oct 2020 23:08:40 +0100 Subject: [PATCH 2/6] add test --- pandas/tests/series/indexing/test_getitem.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pandas/tests/series/indexing/test_getitem.py b/pandas/tests/series/indexing/test_getitem.py index 9f6aab823c3ad..bf047d764ebc1 100644 --- a/pandas/tests/series/indexing/test_getitem.py +++ b/pandas/tests/series/indexing/test_getitem.py @@ -290,3 +290,13 @@ def test_getitem_multilevel_scalar_slice_not_implemented( msg = r"\(2000, slice\(3, 4, None\)\)" with pytest.raises(TypeError, match=msg): ser[2000, 3:4] + + +def test_getitem_assignment_series_aligment(): + # https://github.com/pandas-dev/pandas/issues/37427 + # with getitem, when assigning with a Series, it is not first aligned + s = pd.Series(range(10)) + idx = np.array([2, 4, 9]) + s[idx] = pd.Series([10, 11, 12]) + expected = pd.Series([0, 1, 10, 3, 11, 5, 6, 7, 8, 12]) + tm.assert_series_equal(s, expected) From d55785fe79f85e3d8d98fe71b320a91e37890a1b Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Thu, 29 Oct 2020 23:10:03 +0100 Subject: [PATCH 3/6] add whatsnew --- doc/source/whatsnew/v1.1.4.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.1.4.rst b/doc/source/whatsnew/v1.1.4.rst index 6cb728800dc68..7d35e8b12b9b8 100644 --- a/doc/source/whatsnew/v1.1.4.rst +++ b/doc/source/whatsnew/v1.1.4.rst @@ -28,6 +28,7 @@ Fixed regressions - Fixed regression in certain offsets (:meth:`pd.offsets.Day() ` and below) no longer being hashable (:issue:`37267`) - Fixed regression in :class:`StataReader` which required ``chunksize`` to be manually set when using an iterator to read a dataset (:issue:`37280`) - Fixed regression in setitem with :meth:`DataFrame.iloc` which raised error when trying to set a value while filtering with a boolean list (:issue:`36741`) +- Fixed regression in setitem with a Series getting aligned before setting the values (:issue:`37427`) - Fixed regression in :attr:`MultiIndex.is_monotonic_increasing` returning wrong results with ``NaN`` in at least one of the levels (:issue:`37220`) .. --------------------------------------------------------------------------- From 0df0a528ab2baf94f25bba0b7dc7c00452494506 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Fri, 30 Oct 2020 07:28:27 +0100 Subject: [PATCH 4/6] ignore mypy --- pandas/core/series.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 317db60641132..4b0258ee7355c 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1084,7 +1084,9 @@ def _set_labels(self, key, value): def _set_values(self, key, value): if isinstance(key, Series): key = key._values - self._mgr = self._mgr.setitem(indexer=key, value=value) + self._mgr = self._mgr.setitem( # type: ignore[assignment] + indexer=key, value=value + ) self._maybe_update_cacher() def _set_value(self, label, value, takeable: bool = False): From 278a9a9673d9038a36e5e64e8cf5ef96bfc05fe2 Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Fri, 30 Oct 2020 07:31:27 +0100 Subject: [PATCH 5/6] update error type and message --- pandas/core/series.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/series.py b/pandas/core/series.py index 4b0258ee7355c..2cd861cc11b28 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1078,7 +1078,7 @@ def _set_labels(self, key, value): indexer: np.ndarray = self.index.get_indexer(key) mask = indexer == -1 if mask.any(): - raise ValueError(f"{key[mask]} not contained in the index") + raise KeyError(f"{key[mask]} not in index") self._set_values(indexer, value) def _set_values(self, key, value): From aa7853a2739b036e908abc766a9b07cc067ffdce Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Fri, 30 Oct 2020 08:01:50 +0100 Subject: [PATCH 6/6] linter --- pandas/tests/series/indexing/test_getitem.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/tests/series/indexing/test_getitem.py b/pandas/tests/series/indexing/test_getitem.py index bf047d764ebc1..cc448279bfce0 100644 --- a/pandas/tests/series/indexing/test_getitem.py +++ b/pandas/tests/series/indexing/test_getitem.py @@ -295,8 +295,8 @@ def test_getitem_multilevel_scalar_slice_not_implemented( def test_getitem_assignment_series_aligment(): # https://github.com/pandas-dev/pandas/issues/37427 # with getitem, when assigning with a Series, it is not first aligned - s = pd.Series(range(10)) + s = Series(range(10)) idx = np.array([2, 4, 9]) - s[idx] = pd.Series([10, 11, 12]) - expected = pd.Series([0, 1, 10, 3, 11, 5, 6, 7, 8, 12]) + s[idx] = Series([10, 11, 12]) + expected = Series([0, 1, 10, 3, 11, 5, 6, 7, 8, 12]) tm.assert_series_equal(s, expected)