diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index d100cb0bb70d8..303365f50c546 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -616,6 +616,8 @@ def _get_setitem_indexer(self, key): # invalid indexer type vs 'other' indexing errors if "cannot do" in str(e): raise + elif "unhashable type" in str(e): + raise raise IndexingError(key) from e def _ensure_listlike_indexer(self, key, axis=None): diff --git a/pandas/core/series.py b/pandas/core/series.py index 9182e378fbaeb..854c87071e24a 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -1031,7 +1031,7 @@ def __setitem__(self, key, value): try: self._where(~key, value, inplace=True) except InvalidIndexError: - self._set_values(key.astype(np.bool_), value) + self.iloc[key] = value return else: @@ -1049,8 +1049,10 @@ 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") - return self._set_values(indexer, value) + self.iloc[indexer] = extract_array(value, extract_numpy=True) else: assert not isinstance(key, tuple) @@ -1068,25 +1070,11 @@ 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._set_labels(key, value) + self.loc[key] = value else: - self._set_values(key, value) + self.iloc[key] = value else: - self._set_labels(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() + self.loc[key] = value def _set_value(self, label, value, takeable: bool = False): """ diff --git a/pandas/tests/series/indexing/test_loc.py b/pandas/tests/series/indexing/test_loc.py index 7d6b6c78cc492..368adcfb32215 100644 --- a/pandas/tests/series/indexing/test_loc.py +++ b/pandas/tests/series/indexing/test_loc.py @@ -131,8 +131,8 @@ def test_basic_setitem_with_labels(datetime_series): inds_notfound = [0, 4, 5, 6] arr_inds_notfound = np.array([0, 4, 5, 6]) - msg = r"\[5\] not contained in the index" - with pytest.raises(ValueError, match=msg): + msg = r"\[5\] not in index" + with pytest.raises(KeyError, match=msg): s[inds_notfound] = 0 with pytest.raises(Exception, match=msg): s[arr_inds_notfound] = 0