diff --git a/doc/source/whatsnew/v1.4.2.rst b/doc/source/whatsnew/v1.4.2.rst index 06f1f406c3816..b1d44b1388fdc 100644 --- a/doc/source/whatsnew/v1.4.2.rst +++ b/doc/source/whatsnew/v1.4.2.rst @@ -30,7 +30,7 @@ Bug fixes ~~~~~~~~~ - Fix some cases for subclasses that define their ``_constructor`` properties as general callables (:issue:`46018`) - Fixed "longtable" formatting in :meth:`.Styler.to_latex` when ``column_format`` is given in extended format (:issue:`46037`) -- + .. --------------------------------------------------------------------------- diff --git a/doc/source/whatsnew/v1.5.0.rst b/doc/source/whatsnew/v1.5.0.rst index 8dac952874f89..6aa64380b0a90 100644 --- a/doc/source/whatsnew/v1.5.0.rst +++ b/doc/source/whatsnew/v1.5.0.rst @@ -362,6 +362,7 @@ Conversion - Bug in :meth:`Series.astype` and :meth:`DataFrame.astype` from floating dtype to unsigned integer dtype failing to raise in the presence of negative values (:issue:`45151`) - Bug in :func:`array` with ``FloatingDtype`` and values containing float-castable strings incorrectly raising (:issue:`45424`) - Bug when comparing string and datetime64ns objects causing ``OverflowError`` exception. (:issue:`45506`) +- Bug in :meth:`format.py` the percentiles values are converted to integer dtype, which ignores the floating point error while multiplying. (:issue:`46362`) Strings ^^^^^^^ diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index 609fc2a45aa21..c337b2922f36e 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1713,10 +1713,10 @@ def format_percentiles( percentiles = 100 * percentiles - int_idx = np.isclose(percentiles.astype(int), percentiles) + int_idx = np.isclose(percentiles.round(), percentiles) if np.all(int_idx): - out = percentiles.astype(int).astype(str) + out = percentiles.round().astype(int).astype(str) return [i + "%" for i in out] unique_pcts = np.unique(percentiles) @@ -1729,7 +1729,7 @@ def format_percentiles( ).astype(int) prec = max(1, prec) out = np.empty_like(percentiles, dtype=object) - out[int_idx] = percentiles[int_idx].astype(int).astype(str) + out[int_idx] = percentiles[int_idx].round().astype(int).astype(str) out[~int_idx] = percentiles[~int_idx].round(prec).astype(str) return [i + "%" for i in out] diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index adcaeba5cfd8d..a8e260eaf6e51 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -3262,6 +3262,11 @@ def test_format_percentiles(): expected = ["0%", "50%", "2.0%", "50%", "66.67%", "99.99%"] assert result == expected + # Issue #46362 + result = fmt.format_percentiles([0.281,0.57,0.58,0.29]) + expected = ['28.1%', '57%', '58%', '29%'] + assert result == expected + msg = r"percentiles should all be in the interval \[0,1\]" with pytest.raises(ValueError, match=msg): fmt.format_percentiles([0.1, np.nan, 0.5])