Skip to content

Commit b0dfbaa

Browse files
committed
ENH: Add equivalence test for float in to_numeric() GH43693
1 parent 1cbe011 commit b0dfbaa

File tree

3 files changed

+22
-2
lines changed

3 files changed

+22
-2
lines changed

doc/source/whatsnew/v1.4.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ Other enhancements
228228
- :meth:`.Rolling.var`, :meth:`.Expanding.var`, :meth:`.Rolling.std`, :meth:`.Expanding.std` now support `Numba <http://numba.pydata.org/>`_ execution with the ``engine`` keyword (:issue:`44461`)
229229
- :meth:`Series.info` has been added, for compatibility with :meth:`DataFrame.info` (:issue:`5167`)
230230
- :meth:`UInt64Index.map` now retains ``dtype`` where possible (:issue:`44609`)
231-
-
231+
- :meth:`to_numeric` now preserves float64 arrays when downcasting would generate values not representable in float32 (:issue:`43693`)
232232

233233

234234
.. ---------------------------------------------------------------------------

pandas/core/dtypes/cast.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,17 @@ def trans(x):
352352
and not is_bool_dtype(result.dtype)
353353
and not is_string_dtype(result.dtype)
354354
):
355-
return result.astype(dtype)
355+
new_result = result.astype(dtype)
356+
357+
# Adjust tolerances based on floating point size
358+
size_tols = {4: 5e-4, 8: 5e-8, 16: 5e-16}
359+
360+
atol = size_tols.get(new_result.dtype.itemsize, 0.0)
361+
362+
# Check downcast float values are still equal within 7 digits when
363+
# converting from float64 to float32
364+
if np.allclose(new_result, result, equal_nan=True, rtol=0.0, atol=atol):
365+
return new_result
356366

357367
return result
358368

pandas/tests/tools/test_to_numeric.py

+10
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,14 @@ def test_downcast_limits(dtype, downcast, min_max):
572572
assert series.dtype == dtype
573573

574574

575+
def test_downcast_float64_to_float32():
576+
# GH-43693: Check float64 preservation when >= 16,777,217
577+
series = Series([16777217.0, np.finfo(np.float64).max, np.nan], dtype=np.float64)
578+
result = to_numeric(series, downcast="float")
579+
580+
assert series.dtype == result.dtype
581+
582+
575583
@pytest.mark.parametrize(
576584
"ser,expected",
577585
[
@@ -762,6 +770,8 @@ def test_to_numeric_from_nullable_string(values, nullable_string_dtype, expected
762770
([-1, -1], "Int32", "unsigned", "Int32"),
763771
([1, 1], "Float64", "float", "Float32"),
764772
([1, 1.1], "Float64", "float", "Float32"),
773+
([1, 1], "Float32", "float", "Float32"),
774+
([1, 1.1], "Float32", "float", "Float32"),
765775
),
766776
)
767777
def test_downcast_nullable_numeric(data, input_dtype, downcast, expected_dtype):

0 commit comments

Comments
 (0)