Skip to content

Commit a2f2bff

Browse files
committed
another better patch
1 parent fb52fb6 commit a2f2bff

File tree

6 files changed

+23
-16
lines changed

6 files changed

+23
-16
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,7 @@ Other API changes
404404
- Index set operations (like union or intersection) will now ignore the dtype of
405405
an empty ``RangeIndex`` or empty ``Index`` with object dtype when determining
406406
the dtype of the resulting Index (:issue:`60797`)
407+
- ``np_find_common_type`` will now return ``object`` for mixed ``int64`` and ``uint64`` dtypes to avoid precision lost (:issue:`61676`, :issue:`61688`)
407408

408409
.. ---------------------------------------------------------------------------
409410
.. _whatsnew_300.deprecations:

pandas/core/algorithms.py

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -557,16 +557,6 @@ def f(c, v):
557557

558558
else:
559559
common = np_find_common_type(values.dtype, comps_array.dtype)
560-
if (
561-
values.dtype.kind in "iu"
562-
and comps_array.dtype.kind in "iu"
563-
and common == np.float64
564-
):
565-
# GH#46485
566-
# Let's np_find_common_type do the job and return float64
567-
# when it cannot do otherwise with integers
568-
# We replace it by an object
569-
common = np.dtype("O")
570560
values = values.astype(common, copy=False)
571561
comps_array = comps_array.astype(common, copy=False)
572562
f = htable.ismember

pandas/core/dtypes/cast.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,13 @@ def np_find_common_type(*dtypes: np.dtype) -> np.dtype:
14181418
# so fall back to object (find_common_dtype did unless there
14191419
# was only one dtype)
14201420
common_dtype = np.dtype("O")
1421+
elif (
1422+
# Some precision is lost with float64 when handling uint64/int64
1423+
# Use object instead for the common type
1424+
all(np.dtype(x).kind in "iu" and np.dtype(x).itemsize == 8 for x in dtypes)
1425+
and common_dtype == np.float64
1426+
):
1427+
common_dtype = np.dtype("O")
14211428

14221429
except TypeError:
14231430
common_dtype = np.dtype("O")

pandas/tests/arrays/integer/test_concat.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
(["Int8", "Int16"], "Int16"),
1515
(["UInt8", "Int8"], "Int16"),
1616
(["Int32", "UInt32"], "Int64"),
17-
(["Int64", "UInt64"], "Float64"),
17+
(["Int64", "UInt64"], "object"),
1818
(["Int64", "boolean"], "object"),
1919
(["UInt8", "boolean"], "object"),
2020
],
@@ -48,7 +48,7 @@ def test_concat_series(to_concat_dtypes, result_dtype):
4848
(["Int8", "int16"], "Int16"),
4949
(["UInt8", "int8"], "Int16"),
5050
(["Int32", "uint32"], "Int64"),
51-
(["Int64", "uint64"], "Float64"),
51+
(["Int64", "uint64"], "object"),
5252
(["Int64", "bool"], "object"),
5353
(["UInt8", "bool"], "object"),
5454
],

pandas/tests/dtypes/cast/test_find_common_type.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
((np.float16, np.float32), np.float32),
3232
((np.float16, np.int16), np.float32),
3333
((np.float32, np.int16), np.float32),
34-
((np.uint64, np.int64), np.float64),
34+
((np.uint64, np.int64), object),
3535
((np.int16, np.float64), np.float64),
3636
((np.float16, np.int64), np.float64),
3737
# Into others.
@@ -155,9 +155,16 @@ def test_interval_dtype(left, right):
155155
elif left.subtype.kind in ["i", "u", "f"]:
156156
# i.e. numeric
157157
if right.subtype.kind in ["i", "u", "f"]:
158-
# both numeric -> common numeric subtype
159-
expected = IntervalDtype(np.float64, "right")
160-
assert result == expected
158+
if (
159+
left.subtype.kind in ["i", "u"]
160+
and right.subtype.kind in ["i", "u"]
161+
and left.subtype.kind != right.subtype.kind
162+
):
163+
assert result == object
164+
else:
165+
# both numeric -> common numeric subtype
166+
expected = IntervalDtype(np.float64, "right")
167+
assert result == expected
161168
else:
162169
assert result == object
163170

pandas/tests/indexes/interval/test_setops.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def test_union_empty_result(self, closed, sort):
5555
tm.assert_index_equal(result, expected)
5656

5757
other = empty_index(dtype="uint64", closed=closed)
58+
expected = Index([], dtype='object')
5859
result = index.union(other, sort=sort)
5960
tm.assert_index_equal(result, expected)
6061

@@ -117,6 +118,7 @@ def test_intersection_empty_result(self, closed, sort):
117118
tm.assert_index_equal(result, expected)
118119

119120
other = monotonic_index(300, 314, dtype="uint64", closed=closed)
121+
expected = Index([], dtype='object')
120122
result = index.intersection(other, sort=sort)
121123
tm.assert_index_equal(result, expected)
122124

0 commit comments

Comments
 (0)