diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 6219aa07478d7..3a26c5e44c599 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3089,8 +3089,6 @@ def _intersection(self, other: Index, sort=False): """ intersection specialized to the case with matching dtypes. """ - # TODO(EA): setops-refactor, clean all this up - if self.is_monotonic and other.is_monotonic: try: result = self._inner_indexer(other)[0] @@ -3109,6 +3107,7 @@ def _wrap_intersection_result(self, other, result): # We will override for MultiIndex to handle empty results return self._wrap_setop_result(other, result) + @final def _intersection_via_get_indexer(self, other: Index, sort) -> ArrayLike: """ Find the intersection of two Indexes using get_indexer. @@ -3184,9 +3183,10 @@ def difference(self, other, sort=None): return self.rename(result_name) result = self._difference(other, sort=sort) - return self._wrap_setop_result(other, result) + return self._wrap_difference_result(other, result) def _difference(self, other, sort): + # overridden by RangeIndex this = self.unique() @@ -3199,6 +3199,11 @@ def _difference(self, other, sort): return the_diff + def _wrap_difference_result(self, other, result): + # We will override for MultiIndex to handle empty results + return self._wrap_setop_result(other, result) + + @final def symmetric_difference(self, other, result_name=None, sort=None): """ Compute the symmetric difference of two Index objects. @@ -3246,6 +3251,16 @@ def symmetric_difference(self, other, result_name=None, sort=None): if result_name is not None: result = result.rename(result_name) + + if self._is_multi and len(result) == 0: + # On equal symmetric_difference MultiIndexes the difference is empty. + # Therefore, an empty MultiIndex is returned GH#13490 + return type(self)( + levels=[[] for _ in range(self.nlevels)], + codes=[[] for _ in range(self.nlevels)], + names=result.names, + ) + return result @final diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index d9e9859ea10ed..aed09ef0b9a1d 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -3552,7 +3552,7 @@ def _maybe_match_names(self, other): return names def _wrap_intersection_result(self, other, result): - other, result_names = self._convert_can_do_setop(other) + _, result_names = self._convert_can_do_setop(other) if len(result) == 0: return MultiIndex( @@ -3564,12 +3564,10 @@ def _wrap_intersection_result(self, other, result): else: return MultiIndex.from_arrays(zip(*result), sortorder=0, names=result_names) - def _difference(self, other, sort) -> MultiIndex: - other, result_names = self._convert_can_do_setop(other) - - difference = super()._difference(other, sort) + def _wrap_difference_result(self, other, result): + _, result_names = self._convert_can_do_setop(other) - if len(difference) == 0: + if len(result) == 0: return MultiIndex( levels=[[]] * self.nlevels, codes=[[]] * self.nlevels, @@ -3577,7 +3575,7 @@ def _difference(self, other, sort) -> MultiIndex: verify_integrity=False, ) else: - return MultiIndex.from_tuples(difference, sortorder=0, names=result_names) + return MultiIndex.from_tuples(result, sortorder=0, names=result_names) def _convert_can_do_setop(self, other): result_names = self.names @@ -3599,18 +3597,6 @@ def _convert_can_do_setop(self, other): return other, result_names - def symmetric_difference(self, other, result_name=None, sort=None): - # On equal symmetric_difference MultiIndexes the difference is empty. - # Therefore, an empty MultiIndex is returned GH13490 - tups = Index.symmetric_difference(self, other, result_name, sort) - if len(tups) == 0: - return type(self)( - levels=[[] for _ in range(self.nlevels)], - codes=[[] for _ in range(self.nlevels)], - names=tups.names, - ) - return tups - # -------------------------------------------------------------------- @doc(Index.astype)