From a076e6a5a8d27f828f401ad1c0a0deb443847f55 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Fri, 7 Feb 2020 09:59:02 -0800 Subject: [PATCH 1/2] REF: remove iloc case from _convert_slice_indexer --- pandas/core/indexes/base.py | 20 +++++++++++--------- pandas/core/indexes/numeric.py | 5 ++--- pandas/core/indexing.py | 9 +++++---- pandas/core/series.py | 7 +++++-- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index e431d0bcf7e9b..38af0f7afee44 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3142,6 +3142,15 @@ def _convert_scalar_indexer(self, key, kind: str_t): return key + def _validate_positional_slice(self, key: slice): + """ + For positional indexing, a slice must have either int or None + for each of start, stop, and step. + """ + self._validate_indexer("slice", key.start, "iloc") + self._validate_indexer("slice", key.stop, "iloc") + self._validate_indexer("slice", key.step, "iloc") + def _convert_slice_indexer(self, key: slice, kind=None): """ Convert a slice indexer. @@ -3152,16 +3161,9 @@ def _convert_slice_indexer(self, key: slice, kind=None): Parameters ---------- key : label of the slice bound - kind : {'loc', 'getitem', 'iloc'} or None + kind : {'loc', 'getitem'} or None """ - assert kind in ["loc", "getitem", "iloc", None] - - # validate iloc - if kind == "iloc": - self._validate_indexer("slice", key.start, "iloc") - self._validate_indexer("slice", key.stop, "iloc") - self._validate_indexer("slice", key.step, "iloc") - return key + assert kind in ["loc", "getitem", None], kind # potentially cast the bounds to integers start, stop, step = key.start, key.stop, key.step diff --git a/pandas/core/indexes/numeric.py b/pandas/core/indexes/numeric.py index d67c40a78d807..f09713409c6cf 100644 --- a/pandas/core/indexes/numeric.py +++ b/pandas/core/indexes/numeric.py @@ -394,10 +394,9 @@ def _convert_scalar_indexer(self, key, kind: str): @Appender(Index._convert_slice_indexer.__doc__) def _convert_slice_indexer(self, key: slice, kind=None): + assert kind in ["loc", "getitem", None] - if kind == "iloc": - return super()._convert_slice_indexer(key, kind=kind) - + # We always treat __getitem__ slicing as label-based # translate to locations return self.slice_indexer(key.start, key.stop, key.step, kind=kind) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index bf42cf0330ef0..453154b63f547 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -1752,7 +1752,7 @@ def _get_slice_axis(self, slice_obj: slice, axis: int): labels = obj._get_axis(axis) indexer = labels.slice_indexer( - slice_obj.start, slice_obj.stop, slice_obj.step, kind=self.name + slice_obj.start, slice_obj.stop, slice_obj.step, kind="loc" ) if isinstance(indexer, slice): @@ -2019,8 +2019,8 @@ def _get_slice_axis(self, slice_obj: slice, axis: int): return obj.copy(deep=False) labels = obj._get_axis(axis) - indexer = labels._convert_slice_indexer(slice_obj, kind="iloc") - return self.obj._slice(indexer, axis=axis, kind="iloc") + labels._validate_positional_slice(slice_obj) + return self.obj._slice(slice_obj, axis=axis, kind="iloc") def _convert_to_indexer(self, key, axis: int, is_setter: bool = False): """ @@ -2030,7 +2030,8 @@ def _convert_to_indexer(self, key, axis: int, is_setter: bool = False): # make need to convert a float key if isinstance(key, slice): - return labels._convert_slice_indexer(key, kind="iloc") + labels._validate_positional_slice(key) + return key elif is_float(key): labels._validate_indexer("positional", key, "iloc") diff --git a/pandas/core/series.py b/pandas/core/series.py index 0786674daf874..05c61c014c08e 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -842,7 +842,10 @@ def _ixs(self, i: int, axis: int = 0): def _slice(self, slobj: slice, axis: int = 0, kind: str = "getitem") -> "Series": assert kind in ["getitem", "iloc"] - slobj = self.index._convert_slice_indexer(slobj, kind=kind) + if kind == "getitem": + # If called from getitem, we need to determine whether + # this slice is positional or label-based. + slobj = self.index._convert_slice_indexer(slobj, kind="getitem") return self._get_values(slobj) def __getitem__(self, key): @@ -884,7 +887,7 @@ def __getitem__(self, key): def _get_with(self, key): # other: fancy integer or otherwise if isinstance(key, slice): - return self._slice(key) + return self._slice(key, kind="getitem") elif isinstance(key, ABCDataFrame): raise TypeError( "Indexing a Series with DataFrame is not " From 35c36c735627e6dbf5036be2566a82ad0c2e1a83 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Sun, 9 Feb 2020 08:24:08 -0800 Subject: [PATCH 2/2] post-merge fixup --- pandas/core/indexes/base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 7f1c936849288..c094996f69419 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3147,9 +3147,9 @@ def _validate_positional_slice(self, key: slice): For positional indexing, a slice must have either int or None for each of start, stop, and step. """ - self._validate_indexer("slice", key.start, "iloc") - self._validate_indexer("slice", key.stop, "iloc") - self._validate_indexer("slice", key.step, "iloc") + self._validate_indexer("positional", key.start, "iloc") + self._validate_indexer("positional", key.stop, "iloc") + self._validate_indexer("positional", key.step, "iloc") def _convert_slice_indexer(self, key: slice, kind=None): """