@@ -4941,6 +4941,43 @@ def get_indexer_for(self, target, **kwargs):
4941
4941
indexer , _ = self .get_indexer_non_unique (target )
4942
4942
return indexer
4943
4943
4944
+ def _get_indexer_non_comparable (self , target : "Index" , method , unique : bool = True ):
4945
+ """
4946
+ Called from get_indexer or get_indexer_non_unique when the target
4947
+ is of a non-comparable dtype.
4948
+
4949
+ For get_indexer lookups with method=None, get_indexer is an _equality_
4950
+ check, so non-comparable dtypes mean we will always have no matches.
4951
+
4952
+ For get_indexer lookups with a method, get_indexer is an _inequality_
4953
+ check, so non-comparable dtypes mean we will always raise TypeError.
4954
+
4955
+ Parameters
4956
+ ----------
4957
+ target : Index
4958
+ method : str or None
4959
+ unique : bool, default True
4960
+ * True if called from get_indexer.
4961
+ * False if called from get_indexer_non_unique.
4962
+
4963
+ Raises
4964
+ ------
4965
+ TypeError
4966
+ If doing an inequality check, i.e. method is not None.
4967
+ """
4968
+ if method is not None :
4969
+ other = _unpack_nested_dtype (target )
4970
+ raise TypeError (f"Cannot compare dtypes { self .dtype } and { other .dtype } " )
4971
+
4972
+ no_matches = - 1 * np .ones (target .shape , dtype = np .intp )
4973
+ if unique :
4974
+ # This is for get_indexer
4975
+ return no_matches
4976
+ else :
4977
+ # This is for get_indexer_non_unique
4978
+ missing = np .arange (len (target ), dtype = np .intp )
4979
+ return no_matches , missing
4980
+
4944
4981
@property
4945
4982
def _index_as_unique (self ):
4946
4983
"""
@@ -4976,6 +5013,14 @@ def _maybe_promote(self, other: "Index"):
4976
5013
4977
5014
return self , other
4978
5015
5016
+ def _should_compare (self , other : "Index" ) -> bool :
5017
+ """
5018
+ Check if `self == other` can ever have non-False entries.
5019
+ """
5020
+ other = _unpack_nested_dtype (other )
5021
+ dtype = other .dtype
5022
+ return self ._is_comparable_dtype (dtype ) or is_object_dtype (dtype )
5023
+
4979
5024
def _is_comparable_dtype (self , dtype : DtypeObj ) -> bool :
4980
5025
"""
4981
5026
Can we compare values of the given dtype to our own?
@@ -6123,3 +6168,24 @@ def get_unanimous_names(*indexes: Index) -> Tuple[Label, ...]:
6123
6168
name_sets = [{* ns } for ns in zip_longest (* name_tups )]
6124
6169
names = tuple (ns .pop () if len (ns ) == 1 else None for ns in name_sets )
6125
6170
return names
6171
+
6172
+
6173
+ def _unpack_nested_dtype (other : Index ) -> Index :
6174
+ """
6175
+ When checking if our dtype is comparable with another, we need
6176
+ to unpack CategoricalDtype to look at its categories.dtype.
6177
+
6178
+ Parameters
6179
+ ----------
6180
+ other : Index
6181
+
6182
+ Returns
6183
+ -------
6184
+ Index
6185
+ """
6186
+ dtype = other .dtype
6187
+ if is_categorical_dtype (dtype ):
6188
+ # If there is ever a SparseIndex, this could get dispatched
6189
+ # here too.
6190
+ return dtype .categories
6191
+ return other
0 commit comments