From fc2fd6999815498a77c77da097a0b78760c6853d Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 7 Feb 2020 12:53:14 -0800 Subject: [PATCH 1/3] CLN: indexing cleanups, use iloc instead of loc private method --- pandas/core/frame.py | 8 ++++---- pandas/core/indexes/base.py | 9 ++++----- pandas/core/indexing.py | 6 ++++-- pandas/core/series.py | 4 +++- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index e0efa93379bca..904dd07a72f27 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -2933,12 +2933,12 @@ def __setitem__(self, key, value): # set column self._set_item(key, value) - def _setitem_slice(self, key, value): + def _setitem_slice(self, key: slice, value): # NB: we can't just use self.loc[key] = value because that # operates on labels and we need to operate positional for # backwards-compat, xref GH#31469 self._check_setitem_copy() - self.loc._setitem_with_indexer(key, value) + self.iloc[key] = value def _setitem_array(self, key, value): # also raises Exception if object array with NA values @@ -2950,7 +2950,7 @@ def _setitem_array(self, key, value): key = check_bool_indexer(self.index, key) indexer = key.nonzero()[0] self._check_setitem_copy() - self.loc._setitem_with_indexer(indexer, value) + self.iloc[indexer] = value else: if isinstance(value, DataFrame): if len(value.columns) != len(key): @@ -2962,7 +2962,7 @@ def _setitem_array(self, key, value): key, axis=1, raise_missing=False )[1] self._check_setitem_copy() - self.loc._setitem_with_indexer((slice(None), indexer), value) + self.iloc[:, indexer] = value def _setitem_frame(self, key, value): # support boolean setting with DataFrame input, e.g. diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index e431d0bcf7e9b..ca3416aa6f2fc 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3190,17 +3190,16 @@ def is_int(v): # convert the slice to an indexer here # if we are mixed and have integers - try: - if is_positional and self.is_mixed(): + if is_positional and self.is_mixed(): + try: # Validate start & stop if start is not None: self.get_loc(start) if stop is not None: self.get_loc(stop) is_positional = False - except KeyError: - if self.inferred_type in ["mixed-integer-float", "integer-na"]: - raise + except KeyError: + pass if is_null_slicer: indexer = key diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index bf42cf0330ef0..e418a35c6b792 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -26,8 +26,7 @@ is_list_like_indexer, length_of_indexer, ) -from pandas.core.indexes.api import Index -from pandas.core.indexes.base import InvalidIndexError +from pandas.core.indexes.api import Index, InvalidIndexError # "null slice" _NS = slice(None, None) @@ -592,6 +591,9 @@ def _get_label(self, label, axis: int): return self.obj._xs(label, axis=axis) def _get_setitem_indexer(self, key): + """ + Convert a potentially-label-based key into a positional indexer. + """ if self.axis is not None: return self._convert_tuple(key, is_setter=True) diff --git a/pandas/core/series.py b/pandas/core/series.py index 0786674daf874..c89456d43d1d6 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -862,7 +862,9 @@ def __getitem__(self, key): return result except InvalidIndexError: - pass + if not isinstance(self.index, MultiIndex): + raise + except (KeyError, ValueError): if isinstance(key, tuple) and isinstance(self.index, MultiIndex): # kludge From 58c6f48a6da96e99b4f0b95b55d1f1f64567319d Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 7 Feb 2020 14:25:14 -0800 Subject: [PATCH 2/3] consistently dont return anything from _setitem_with_indexer --- pandas/core/indexing.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index e418a35c6b792..87a77bdf09c0d 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -792,7 +792,7 @@ def _setitem_with_indexer(self, indexer, value): "defined index and a scalar" ) self.obj[key] = value - return self.obj + return # add a new item with the dtype setup self.obj[key] = _infer_fill_value(value) @@ -802,7 +802,7 @@ def _setitem_with_indexer(self, indexer, value): ) self._setitem_with_indexer(new_indexer, value) - return self.obj + return # reindex the axis # make sure to clear the cache because we are @@ -825,7 +825,8 @@ def _setitem_with_indexer(self, indexer, value): indexer, missing = convert_missing_indexer(indexer) if missing: - return self._setitem_with_indexer_missing(indexer, value) + self._setitem_with_indexer_missing(indexer, value) + return # set item_labels = self.obj._get_axis(info_axis) @@ -1051,7 +1052,6 @@ def _setitem_with_indexer_missing(self, indexer, value): new_values, index=new_index, name=self.obj.name )._data self.obj._maybe_update_cacher(clear=True) - return self.obj elif self.ndim == 2: @@ -1075,7 +1075,6 @@ def _setitem_with_indexer_missing(self, indexer, value): self.obj._data = self.obj.append(value)._data self.obj._maybe_update_cacher(clear=True) - return self.obj def _align_series(self, indexer, ser: ABCSeries, multiindex_indexer: bool = False): """ From 3106a7702ffd9fec99224fad653639b3c1ce3fce Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sat, 8 Feb 2020 08:54:55 -0800 Subject: [PATCH 3/3] revert --- pandas/core/frame.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/core/frame.py b/pandas/core/frame.py index 904dd07a72f27..c6f77591de033 100644 --- a/pandas/core/frame.py +++ b/pandas/core/frame.py @@ -2938,7 +2938,7 @@ def _setitem_slice(self, key: slice, value): # operates on labels and we need to operate positional for # backwards-compat, xref GH#31469 self._check_setitem_copy() - self.iloc[key] = value + self.iloc._setitem_with_indexer(key, value) def _setitem_array(self, key, value): # also raises Exception if object array with NA values @@ -2950,7 +2950,7 @@ def _setitem_array(self, key, value): key = check_bool_indexer(self.index, key) indexer = key.nonzero()[0] self._check_setitem_copy() - self.iloc[indexer] = value + self.iloc._setitem_with_indexer(indexer, value) else: if isinstance(value, DataFrame): if len(value.columns) != len(key): @@ -2962,7 +2962,7 @@ def _setitem_array(self, key, value): key, axis=1, raise_missing=False )[1] self._check_setitem_copy() - self.iloc[:, indexer] = value + self.iloc._setitem_with_indexer((slice(None), indexer), value) def _setitem_frame(self, key, value): # support boolean setting with DataFrame input, e.g.