diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 5bffc4ec552af..d30765217390f 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -3243,9 +3243,13 @@ def union(self, other, sort=None): # TODO: Index.union returns other when `len(self)` is 0. - uniq_tuples = lib.fast_unique_multiple( - [self._values, other._ndarray_values], sort=sort - ) + if not is_object_dtype(other.dtype): + raise NotImplementedError( + "Can only union MultiIndex with MultiIndex or Index of tuples, " + "try mi.to_flat_index().union(other) instead." + ) + + uniq_tuples = lib.fast_unique_multiple([self._values, other._values], sort=sort) return MultiIndex.from_arrays( zip(*uniq_tuples), sortorder=0, names=result_names @@ -3279,8 +3283,18 @@ def intersection(self, other, sort=False): if self.equals(other): return self + if not is_object_dtype(other.dtype): + # The intersection is empty + # TODO: we have no tests that get here + return MultiIndex( + levels=self.levels, + codes=[[]] * self.nlevels, + names=result_names, + verify_integrity=False, + ) + lvals = self._values - rvals = other._ndarray_values + rvals = other._values uniq_tuples = None # flag whether _inner_indexer was succesful if self.is_monotonic and other.is_monotonic: diff --git a/pandas/tests/indexes/multi/test_setops.py b/pandas/tests/indexes/multi/test_setops.py index d7d0ff4c411aa..b24f56afee376 100644 --- a/pandas/tests/indexes/multi/test_setops.py +++ b/pandas/tests/indexes/multi/test_setops.py @@ -246,6 +246,7 @@ def test_union(idx, sort): the_union = idx.union(idx[:0], sort=sort) assert the_union is idx + # FIXME: dont leave commented-out # won't work in python 3 # tuples = _index.values # result = _index[:4] | tuples[4:] @@ -282,6 +283,7 @@ def test_intersection(idx, sort): expected = idx[:0] assert empty.equals(expected) + # FIXME: dont leave commented-out # can't do in python 3 # tuples = _index.values # result = _index & tuples @@ -351,6 +353,17 @@ def test_union_sort_other_incomparable_sort(): idx.union(idx[:1], sort=True) +def test_union_non_object_dtype_raises(): + # GH#32646 raise NotImplementedError instead of less-informative error + mi = pd.MultiIndex.from_product([["a", "b"], [1, 2]]) + + idx = mi.levels[1] + + msg = "Can only union MultiIndex with MultiIndex or Index of tuples" + with pytest.raises(NotImplementedError, match=msg): + mi.union(idx) + + @pytest.mark.parametrize( "method", ["union", "intersection", "difference", "symmetric_difference"] )