@@ -2656,12 +2656,59 @@ def union(self, other, sort=None):
2656
2656
>>> idx2 = pd.Index([1, 2, 3, 4])
2657
2657
>>> idx1.union(idx2)
2658
2658
Index(['a', 'b', 'c', 'd', 1, 2, 3, 4], dtype='object')
2659
+
2660
+ MultiIndex case
2661
+
2662
+ >>> idx1 = pd.MultiIndex.from_arrays(
2663
+ ... [[1, 1, 2, 2], ["Red", "Blue", "Red", "Blue"]]
2664
+ ... )
2665
+ >>> idx1
2666
+ MultiIndex([(1, 'Red'),
2667
+ (1, 'Blue'),
2668
+ (2, 'Red'),
2669
+ (2, 'Blue')],
2670
+ )
2671
+ >>> idx2 = pd.MultiIndex.from_arrays(
2672
+ ... [[3, 3, 2, 2], ["Red", "Green", "Red", "Green"]]
2673
+ ... )
2674
+ >>> idx2
2675
+ MultiIndex([(3, 'Red'),
2676
+ (3, 'Green'),
2677
+ (2, 'Red'),
2678
+ (2, 'Green')],
2679
+ )
2680
+ >>> idx1.union(idx2)
2681
+ MultiIndex([(1, 'Blue'),
2682
+ (1, 'Red'),
2683
+ (2, 'Blue'),
2684
+ (2, 'Green'),
2685
+ (2, 'Red'),
2686
+ (3, 'Green'),
2687
+ (3, 'Red')],
2688
+ )
2689
+ >>> idx1.union(idx2, sort=False)
2690
+ MultiIndex([(1, 'Red'),
2691
+ (1, 'Blue'),
2692
+ (2, 'Red'),
2693
+ (2, 'Blue'),
2694
+ (3, 'Red'),
2695
+ (3, 'Green'),
2696
+ (2, 'Green')],
2697
+ )
2659
2698
"""
2660
2699
self ._validate_sort_keyword (sort )
2661
2700
self ._assert_can_do_setop (other )
2662
2701
other , result_name = self ._convert_can_do_setop (other )
2663
2702
2664
2703
if not is_dtype_equal (self .dtype , other .dtype ):
2704
+ if isinstance (self , ABCMultiIndex ) and not is_object_dtype (
2705
+ unpack_nested_dtype (other )
2706
+ ):
2707
+ raise NotImplementedError (
2708
+ "Can only union MultiIndex with MultiIndex or Index of tuples, "
2709
+ "try mi.to_flat_index().union(other) instead."
2710
+ )
2711
+
2665
2712
dtype = find_common_type ([self .dtype , other .dtype ])
2666
2713
if self ._is_numeric_dtype and other ._is_numeric_dtype :
2667
2714
# Right now, we treat union(int, float) a bit special.
@@ -2680,6 +2727,14 @@ def union(self, other, sort=None):
2680
2727
right = other .astype (dtype , copy = False )
2681
2728
return left .union (right , sort = sort )
2682
2729
2730
+ elif not len (other ) or self .equals (other ):
2731
+ # NB: whether this (and the `if not len(self)` check below) come before
2732
+ # or after the is_dtype_equal check above affects the returned dtype
2733
+ return self ._get_reconciled_name_object (other )
2734
+
2735
+ elif not len (self ):
2736
+ return other ._get_reconciled_name_object (self )
2737
+
2683
2738
result = self ._union (other , sort = sort )
2684
2739
2685
2740
return self ._wrap_setop_result (other , result )
@@ -2703,12 +2758,6 @@ def _union(self, other, sort):
2703
2758
-------
2704
2759
Index
2705
2760
"""
2706
- if not len (other ) or self .equals (other ):
2707
- return self
2708
-
2709
- if not len (self ):
2710
- return other
2711
-
2712
2761
# TODO(EA): setops-refactor, clean all this up
2713
2762
lvals = self ._values
2714
2763
rvals = other ._values
0 commit comments