Specific union logic should go here. In subclasses, union behavior should be overwritten here rather than in `self.union`. Parameters ---------- other : Index or array-like sort : False or None, default False Whether to sort the resulting
(self, other: Index, sort: bool | None)
| 3154 | return self._wrap_setop_result(other, result) |
| 3155 | |
| 3156 | def _union(self, other: Index, sort: bool | None): |
| 3157 | """ |
| 3158 | Specific union logic should go here. In subclasses, union behavior |
| 3159 | should be overwritten here rather than in `self.union`. |
| 3160 | |
| 3161 | Parameters |
| 3162 | ---------- |
| 3163 | other : Index or array-like |
| 3164 | sort : False or None, default False |
| 3165 | Whether to sort the resulting index. |
| 3166 | |
| 3167 | * True : sort the result |
| 3168 | * False : do not sort the result. |
| 3169 | * None : sort the result, except when `self` and `other` are equal |
| 3170 | or when the values cannot be compared. |
| 3171 | |
| 3172 | Returns |
| 3173 | ------- |
| 3174 | Index |
| 3175 | """ |
| 3176 | lvals = self._values |
| 3177 | rvals = other._values |
| 3178 | |
| 3179 | if ( |
| 3180 | sort in (None, True) |
| 3181 | and (self.is_unique or other.is_unique) |
| 3182 | and self._can_use_libjoin |
| 3183 | and other._can_use_libjoin |
| 3184 | ): |
| 3185 | # Both are monotonic and at least one is unique, so can use outer join |
| 3186 | # (actually don't need either unique, but without this restriction |
| 3187 | # test_union_same_value_duplicated_in_both fails) |
| 3188 | try: |
| 3189 | return self._outer_indexer(other)[0] |
| 3190 | except TypeError: |
| 3191 | # incomparable objects; should only be for object dtype |
| 3192 | value_list = list(lvals) |
| 3193 | |
| 3194 | # worth making this faster? a very unusual case |
| 3195 | value_set = set(lvals) |
| 3196 | value_list.extend(x for x in rvals if x not in value_set) |
| 3197 | # If objects are unorderable, we must have object dtype. |
| 3198 | return np.array(value_list, dtype=object) |
| 3199 | |
| 3200 | elif not other.is_unique: |
| 3201 | # other has duplicates |
| 3202 | result_dups = algos.union_with_duplicates(self, other) |
| 3203 | return _maybe_try_sort(result_dups, sort) |
| 3204 | |
| 3205 | # The rest of this method is analogous to Index._intersection_via_get_indexer |
| 3206 | |
| 3207 | # Self may have duplicates; other already checked as unique |
| 3208 | # find indexes of things in "other" that are not in "self" |
| 3209 | if self._index_as_unique: |
| 3210 | indexer = self.get_indexer(other) |
| 3211 | missing = (indexer == -1).nonzero()[0] |
| 3212 | else: |
| 3213 | missing = algos.unique1d(self.get_indexer_non_unique(other)[1]) |