From 38154b15d0e787481046e98437047ce412d944df Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 27 Jan 2020 10:20:08 -0800 Subject: [PATCH] BUG/REF: multiindex nested tuples with duplicates --- pandas/core/indexes/multi.py | 3 ++- pandas/core/indexing.py | 3 ++- pandas/tests/indexes/multi/test_indexing.py | 2 +- .../indexing/multiindex/test_multiindex.py | 19 +++++++++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 488f3617f2c3c..a380ef03e0b35 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2643,7 +2643,8 @@ def _maybe_to_slice(loc): mask[loc] = True return mask - if not isinstance(key, tuple): + if not isinstance(key, (tuple, list)): + # not including list here breaks some indexing, xref #30892 loc = self._get_level_indexer(key, level=0) return _maybe_to_slice(loc) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index f88ad0287440d..d79f0f484c5fe 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -28,6 +28,7 @@ length_of_indexer, ) from pandas.core.indexes.api import Index +from pandas.core.indexes.base import InvalidIndexError # "null slice" _NS = slice(None, None) @@ -606,7 +607,7 @@ def _get_setitem_indexer(self, key): if isinstance(ax, ABCMultiIndex) and self.name != "iloc": try: return ax.get_loc(key) - except (TypeError, KeyError): + except (TypeError, KeyError, InvalidIndexError): # TypeError e.g. passed a bool pass diff --git a/pandas/tests/indexes/multi/test_indexing.py b/pandas/tests/indexes/multi/test_indexing.py index 9070eb3deffb5..b08280a712642 100644 --- a/pandas/tests/indexes/multi/test_indexing.py +++ b/pandas/tests/indexes/multi/test_indexing.py @@ -396,7 +396,7 @@ def test_get_loc_missing_nan(): idx.get_loc(3) with pytest.raises(KeyError, match=r"^nan$"): idx.get_loc(np.nan) - with pytest.raises(TypeError, match=r"'\[nan\]' is an invalid key"): + with pytest.raises(TypeError, match="unhashable type: 'list'"): # listlike/non-hashable raises TypeError idx.get_loc([np.nan]) diff --git a/pandas/tests/indexing/multiindex/test_multiindex.py b/pandas/tests/indexing/multiindex/test_multiindex.py index 8163de8588232..0064187a94265 100644 --- a/pandas/tests/indexing/multiindex/test_multiindex.py +++ b/pandas/tests/indexing/multiindex/test_multiindex.py @@ -92,3 +92,22 @@ def test_contains(self): assert tx[0] in idx assert "element_not_exit" not in idx assert "0 day 09:30:00" in idx + + def test_nested_tuples_duplicates(self): + # GH#30892 + + dti = pd.to_datetime(["20190101", "20190101", "20190102"]) + idx = pd.Index(["a", "a", "c"]) + mi = pd.MultiIndex.from_arrays([dti, idx], names=["index1", "index2"]) + + df = pd.DataFrame({"c1": [1, 2, 3], "c2": [np.nan, np.nan, np.nan]}, index=mi) + + expected = pd.DataFrame({"c1": df["c1"], "c2": [1.0, 1.0, np.nan]}, index=mi) + + df2 = df.copy(deep=True) + df2.loc[(dti[0], "a"), "c2"] = 1.0 + tm.assert_frame_equal(df2, expected) + + df3 = df.copy(deep=True) + df3.loc[[(dti[0], "a")], "c2"] = 1.0 + tm.assert_frame_equal(df3, expected)