From 2874a9e080d71ba26cbaab2b0687d5791b7b917d Mon Sep 17 00:00:00 2001 From: tp Date: Thu, 28 Sep 2017 13:38:05 +0200 Subject: [PATCH 1/4] Add examples to MultiIndex.slice_locs + note that index.slice requires monotonic ordering --- pandas/core/indexes/base.py | 15 ++++++++++++++- pandas/core/indexes/multi.py | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index c4e1398d0178f..2e0d8ec191afc 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3556,7 +3556,7 @@ def get_slice_bound(self, label, side, kind): def slice_locs(self, start=None, end=None, step=None, kind=None): """ - Compute slice locations for input labels. + For an ordered index, compute slice locations for input labels. Parameters ---------- @@ -3572,6 +3572,19 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): ------- start, end : int + Notes + ----- + This method only works if the index is monotonic. + + Examples + --------- + >>> idx = pd.Index(list('abcd')) + >>> idx.slice_locs(start='b', end='c') + (1, 3) + + See Also + -------- + Index.get_loc : Get location for a single label """ inc = (step is None or step >= 0) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 9ffac0832062d..70e76dd588e56 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -1924,7 +1924,9 @@ def get_slice_bound(self, label, side, kind): def slice_locs(self, start=None, end=None, step=None, kind=None): """ For an ordered MultiIndex, compute the slice locations for input - labels. They can be tuples representing partial levels, e.g. for a + labels. + + The input labels can be tuples representing partial levels, e.g. for a MultiIndex with 3 levels, you can pass a single value (corresponding to the first level), or a 1-, 2-, or 3-tuple. @@ -1944,7 +1946,32 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): Notes ----- - This function assumes that the data is sorted by the first level + This method only works if the MultiIndex is properly lex-sorted. So, + if only the first 2 levels of a 3-level MultiIndex are lexsorted, + you can only pass two levels to ``.slice_locs``. + + Examples + -------- + mi = pd.MultiIndex.from_arrays([list('abbd'), list('deff')], + names=['A', 'B']) + + Get the slice locations from the beginning of 'b' in the first level + until the end of the multiindex: + + mi.slice_locs(start='b') + (1, 4) + + Like above, but stop at the end of 'b' in the first level and 'f' in + the second level: + + mi.slice_locs(start='b', end=('b', 'f')) + (1, 3) + + See Also + -------- + MultiIndex.get_loc : Get location for a label or a tuple of labels. + MultiIndex.get_locs : Get location for a label/slice/list/mask or a + sequence of such. """ # This function adds nothing to its parent implementation (the magic # happens in get_slice_bound method), but it adds meaningful doc. @@ -2015,6 +2042,8 @@ def get_loc(self, key, method=None): See also -------- Index.get_loc : get_loc method for (single-level) index. + MultiIndex.slice_locs : Get slice location given startlabel(s) and + endlabel(s). MultiIndex.get_locs : Get location for a label/slice/list/mask or a sequence of such. """ @@ -2368,6 +2397,8 @@ def get_locs(self, seq): See also -------- MultiIndex.get_loc : Get location for a label or a tuple of labels. + MultiIndex.slice_locs : Get slice location given startlabel(s) and + endlabel(s). """ # must be lexsorted to at least as many levels From 1e5fd282d4244409bbf5fadf291aa6b773ca9a7e Mon Sep 17 00:00:00 2001 From: tp Date: Fri, 6 Oct 2017 09:51:18 +0200 Subject: [PATCH 2/4] clarify that slice_locs also works with unique index --- pandas/core/indexes/base.py | 4 ++-- pandas/core/indexes/multi.py | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 2e0d8ec191afc..ad9ffaa90b8c9 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3556,7 +3556,7 @@ def get_slice_bound(self, label, side, kind): def slice_locs(self, start=None, end=None, step=None, kind=None): """ - For an ordered index, compute slice locations for input labels. + Compute slice locations for input labels. Parameters ---------- @@ -3574,7 +3574,7 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): Notes ----- - This method only works if the index is monotonic. + This method only works if the index is monotonic or unique. Examples --------- diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 70e76dd588e56..ea929a54b9962 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -1952,19 +1952,19 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): Examples -------- - mi = pd.MultiIndex.from_arrays([list('abbd'), list('deff')], - names=['A', 'B']) + >>> mi = pd.MultiIndex.from_arrays([list('abbd'), list('deff')], + ... names=['A', 'B']) Get the slice locations from the beginning of 'b' in the first level until the end of the multiindex: - mi.slice_locs(start='b') + >>> mi.slice_locs(start='b') (1, 4) Like above, but stop at the end of 'b' in the first level and 'f' in the second level: - mi.slice_locs(start='b', end=('b', 'f')) + >>> mi.slice_locs(start='b', end=('b', 'f')) (1, 3) See Also @@ -2042,8 +2042,8 @@ def get_loc(self, key, method=None): See also -------- Index.get_loc : get_loc method for (single-level) index. - MultiIndex.slice_locs : Get slice location given startlabel(s) and - endlabel(s). + MultiIndex.slice_locs : Get slice location given start label(s) and + end label(s). MultiIndex.get_locs : Get location for a label/slice/list/mask or a sequence of such. """ @@ -2397,8 +2397,8 @@ def get_locs(self, seq): See also -------- MultiIndex.get_loc : Get location for a label or a tuple of labels. - MultiIndex.slice_locs : Get slice location given startlabel(s) and - endlabel(s). + MultiIndex.slice_locs : Get slice location given start label(s) and + end label(s). """ # must be lexsorted to at least as many levels From a642a6d086a4bf25cc5ec1e8284d881a41356e7d Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Fri, 6 Oct 2017 13:45:37 +0200 Subject: [PATCH 3/4] spacing --- pandas/core/indexes/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index ad9ffaa90b8c9..29aace2a94c5a 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3579,7 +3579,7 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): Examples --------- >>> idx = pd.Index(list('abcd')) - >>> idx.slice_locs(start='b', end='c') + >>> idx.slice_locs(start='b', end='c') (1, 3) See Also From d41388bc2f9e8daf0dc72f83316d0e2d49e18a3a Mon Sep 17 00:00:00 2001 From: Joris Van den Bossche Date: Fri, 6 Oct 2017 13:46:13 +0200 Subject: [PATCH 4/4] spacing --- pandas/core/indexes/multi.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index ea929a54b9962..f091a2b74596f 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -1947,7 +1947,7 @@ def slice_locs(self, start=None, end=None, step=None, kind=None): Notes ----- This method only works if the MultiIndex is properly lex-sorted. So, - if only the first 2 levels of a 3-level MultiIndex are lexsorted, + if only the first 2 levels of a 3-level MultiIndex are lexsorted, you can only pass two levels to ``.slice_locs``. Examples