diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index b89ead2fe7b47..5a3bce383629f 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2541,7 +2541,7 @@ def _partial_tup_index(self, tup, side="left"): for k, (lab, lev, labs) in enumerate(zipped): section = labs[start:end] - if lab not in lev and not isna(lab): + if lab not in lev and np.ndim(lab) == 0 and not isna(lab): if not lev.is_type_compatible(lib.infer_dtype([lab], skipna=False)): raise TypeError(f"Level type mismatch: {lab}") @@ -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 2db5e8190b00f..fd4bca79f7c62 100755 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -639,7 +639,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 ad6f06d065150..b08280a712642 100644 --- a/pandas/tests/indexes/multi/test_indexing.py +++ b/pandas/tests/indexes/multi/test_indexing.py @@ -396,7 +396,8 @@ 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(KeyError, match=r"^\[nan\]$"): + 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)