Skip to content

Commit 6a037b1

Browse files
committed
ENH: Add equivalence test for float in to_numeric() GH43693
1 parent 69f4ccf commit 6a037b1

File tree

3 files changed

+22
-1
lines changed

3 files changed

+22
-1
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ Other enhancements
225225
- :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`).
226226
- Add support for `Zstandard <http://facebook.github.io/zstd/>`_ compression to :meth:`DataFrame.to_pickle`/:meth:`read_pickle` and friends (:issue:`43925`)
227227
- :meth:`DataFrame.to_sql` now returns an ``int`` of the number of written rows (:issue:`23998`)
228+
- :meth:`to_numeric` now preserves float64 arrays when downcasting would generate values not representable in float32 (:issue:`43693`)
228229

229230
.. ---------------------------------------------------------------------------
230231

pandas/core/dtypes/cast.py

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

359369
return result
360370

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)