Skip to content

Commit 421fb8d

Browse files
authored
REF: implement Index._find_common_type_compat (#39408)
1 parent 3f07983 commit 421fb8d

File tree

2 files changed

+32
-17
lines changed

2 files changed

+32
-17
lines changed

pandas/core/indexes/base.py

+17-10
Original file line numberDiff line numberDiff line change
@@ -3312,7 +3312,8 @@ def _get_indexer(
33123312
tolerance = self._convert_tolerance(tolerance, target)
33133313

33143314
if not is_dtype_equal(self.dtype, target.dtype):
3315-
dtype = find_common_type([self.dtype, target.dtype])
3315+
dtype = self._find_common_type_compat(target)
3316+
33163317
this = self.astype(dtype, copy=False)
33173318
target = target.astype(dtype, copy=False)
33183319
return this.get_indexer(
@@ -5075,15 +5076,7 @@ def get_indexer_non_unique(self, target):
50755076
if not is_dtype_equal(self.dtype, target.dtype):
50765077
# TODO: if object, could use infer_dtype to preempt costly
50775078
# conversion if still non-comparable?
5078-
dtype = find_common_type([self.dtype, target.dtype])
5079-
if (
5080-
dtype.kind in ["i", "u"]
5081-
and is_categorical_dtype(target.dtype)
5082-
and target.hasnans
5083-
):
5084-
# FIXME: find_common_type incorrect with Categorical GH#38240
5085-
# FIXME: some cases where float64 cast can be lossy?
5086-
dtype = np.dtype(np.float64)
5079+
dtype = self._find_common_type_compat(target)
50875080

50885081
this = self.astype(dtype, copy=False)
50895082
that = target.astype(dtype, copy=False)
@@ -5196,6 +5189,20 @@ def _maybe_promote(self, other: Index):
51965189

51975190
return self, other
51985191

5192+
def _find_common_type_compat(self, target: Index) -> DtypeObj:
5193+
"""
5194+
Implementation of find_common_type that adjusts for Index-specific
5195+
special cases.
5196+
"""
5197+
dtype = find_common_type([self.dtype, target.dtype])
5198+
if dtype.kind in ["i", "u"]:
5199+
# TODO: what about reversed with self being categorical?
5200+
if is_categorical_dtype(target.dtype) and target.hasnans:
5201+
# FIXME: find_common_type incorrect with Categorical GH#38240
5202+
# FIXME: some cases where float64 cast can be lossy?
5203+
dtype = np.dtype(np.float64)
5204+
return dtype
5205+
51995206
@final
52005207
def _should_compare(self, other: Index) -> bool:
52015208
"""

pandas/tests/arrays/categorical/test_indexing.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -212,17 +212,25 @@ def test_categories_assignments_wrong_length_raises(self, new_categories):
212212
# Combinations of missing/unique
213213
@pytest.mark.parametrize("key_values", [[1, 2], [1, 5], [1, 1], [5, 5]])
214214
@pytest.mark.parametrize("key_class", [Categorical, CategoricalIndex])
215-
def test_get_indexer_non_unique(self, idx_values, key_values, key_class):
215+
@pytest.mark.parametrize("dtype", [None, "category", "key"])
216+
def test_get_indexer_non_unique(self, idx_values, key_values, key_class, dtype):
216217
# GH 21448
217218
key = key_class(key_values, categories=range(1, 5))
219+
220+
if dtype == "key":
221+
dtype = key.dtype
222+
218223
# Test for flat index and CategoricalIndex with same/different cats:
219-
for dtype in [None, "category", key.dtype]:
220-
idx = Index(idx_values, dtype=dtype)
221-
expected, exp_miss = idx.get_indexer_non_unique(key_values)
222-
result, res_miss = idx.get_indexer_non_unique(key)
224+
idx = Index(idx_values, dtype=dtype)
225+
expected, exp_miss = idx.get_indexer_non_unique(key_values)
226+
result, res_miss = idx.get_indexer_non_unique(key)
227+
228+
tm.assert_numpy_array_equal(expected, result)
229+
tm.assert_numpy_array_equal(exp_miss, res_miss)
223230

224-
tm.assert_numpy_array_equal(expected, result)
225-
tm.assert_numpy_array_equal(exp_miss, res_miss)
231+
exp_unique = idx.unique().get_indexer(key_values)
232+
res_unique = idx.unique().get_indexer(key)
233+
tm.assert_numpy_array_equal(res_unique, exp_unique)
226234

227235
def test_where_unobserved_nan(self):
228236
ser = Series(Categorical(["a", "b"]))

0 commit comments

Comments
 (0)