Skip to content

Commit 5879125

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

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

doc/source/whatsnew/v1.4.0.rst

+1-2
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,7 @@ Other enhancements
234234
- :meth:`DataFrame.take` now raises a ``TypeError`` when passed a scalar for the indexer (:issue:`42875`)
235235
- :meth:`is_list_like` now identifies duck-arrays as list-like unless ``.ndim == 0`` (:issue:`35131`)
236236
- :class:`ExtensionDtype` and :class:`ExtensionArray` are now (de)serialized when exporting a :class:`DataFrame` with :meth:`DataFrame.to_json` using ``orient='table'`` (:issue:`20612`, :issue:`44705`).
237-
-
238-
237+
- :meth:`to_numeric` now preserves float64 arrays when downcasting would generate values not representable in float32 (:issue:`43693`)
239238

240239
.. ---------------------------------------------------------------------------
241240

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)