@@ -3254,12 +3254,47 @@ def symmetric_difference(self, other, result_name=None, sort=None):
3254
3254
if result_name is None :
3255
3255
result_name = result_name_update
3256
3256
3257
- left = self .difference (other , sort = False )
3258
- right = other .difference (self , sort = False )
3259
- result = left .union (right , sort = sort )
3257
+ if not self ._should_compare (other ):
3258
+ return self .union (other , sort = sort ).rename (result_name )
3259
+
3260
+ elif not is_dtype_equal (self .dtype , other .dtype ):
3261
+ dtype = self ._find_common_type_compat (other )
3262
+ this = self .astype (dtype , copy = False )
3263
+ that = other .astype (dtype , copy = False )
3264
+ return this .symmetric_difference (that , sort = sort ).rename (result_name )
3265
+
3266
+ this = self .unique ()
3267
+ other = other .unique ()
3268
+ indexer = this .get_indexer_for (other )
3269
+
3270
+ # {this} minus {other}
3271
+ common_indexer = indexer .take ((indexer != - 1 ).nonzero ()[0 ])
3272
+ left_indexer = np .setdiff1d (
3273
+ np .arange (this .size ), common_indexer , assume_unique = True
3274
+ )
3275
+ left_diff = this ._values .take (left_indexer )
3276
+
3277
+ # {other} minus {this}
3278
+ right_indexer = (indexer == - 1 ).nonzero ()[0 ]
3279
+ right_diff = other ._values .take (right_indexer )
3280
+
3281
+ res_values = concat_compat ([left_diff , right_diff ])
3282
+ res_values = _maybe_try_sort (res_values , sort )
3283
+
3284
+ result = Index (res_values , name = result_name )
3285
+
3286
+ if self ._is_multi :
3287
+ self = cast ("MultiIndex" , self )
3288
+ if len (result ) == 0 :
3289
+ # On equal symmetric_difference MultiIndexes the difference is empty.
3290
+ # Therefore, an empty MultiIndex is returned GH#13490
3291
+ return type (self )(
3292
+ levels = [[] for _ in range (self .nlevels )],
3293
+ codes = [[] for _ in range (self .nlevels )],
3294
+ names = result .name ,
3295
+ )
3296
+ return type (self ).from_tuples (result , names = result .name )
3260
3297
3261
- if result_name is not None :
3262
- result = result .rename (result_name )
3263
3298
return result
3264
3299
3265
3300
@final
0 commit comments