Skip to content

Commit 4546015

Browse files
authored
ENH: Add equivalence test for float in to_numeric() GH43693 (#43710)
1 parent 56498ae commit 4546015

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ Other enhancements
3333
^^^^^^^^^^^^^^^^^^
3434
- :class:`StringArray` now accepts array-likes containing nan-likes (``None``, ``np.nan``) for the ``values`` parameter in its constructor in addition to strings and :attr:`pandas.NA`. (:issue:`40839`)
3535
- Improved the rendering of ``categories`` in :class:`CategoricalIndex` (:issue:`45218`)
36+
- :meth:`to_numeric` now preserves float64 arrays when downcasting would generate values not representable in float32 (:issue:`43693`)
3637
-
3738

3839
.. ---------------------------------------------------------------------------

pandas/core/dtypes/cast.py

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

362372
return result
363373

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)