From b1787b2b40104e39eb945134688146cac0621af4 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Mon, 21 Jan 2019 17:31:49 +0100 Subject: [PATCH 1/3] BUG: fix floating precision formatting in presence of inf --- pandas/io/formats/format.py | 14 +++++++---- pandas/tests/io/formats/test_format.py | 33 ++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index bdeed58d856cc..f8a739177a1ae 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1414,16 +1414,20 @@ def _trim_zeros(str_floats, na_rep='NaN'): """ trimmed = str_floats + def _is_number(x): + return (x != na_rep and not x.endswith('inf')) + def _cond(values): - non_na = [x for x in values if x != na_rep] - return (len(non_na) > 0 and all(x.endswith('0') for x in non_na) and - not (any(('e' in x) or ('E' in x) for x in non_na))) + finite = [x for x in values if _is_number(x)] + return (len(finite) > 0 and all(x.endswith('0') for x in finite) and + not (any(('e' in x) or ('E' in x) for x in finite))) while _cond(trimmed): - trimmed = [x[:-1] if x != na_rep else x for x in trimmed] + trimmed = [x[:-1] if _is_number(x) else x for x in trimmed] # leave one 0 after the decimal points if need be. - return [x + "0" if x.endswith('.') and x != na_rep else x for x in trimmed] + return [x + "0" if x.endswith('.') and _is_number(x) else x + for x in trimmed] def _has_names(index): diff --git a/pandas/tests/io/formats/test_format.py b/pandas/tests/io/formats/test_format.py index 52dce572c6d4f..31ab1e050d95c 100644 --- a/pandas/tests/io/formats/test_format.py +++ b/pandas/tests/io/formats/test_format.py @@ -1465,6 +1465,39 @@ def test_to_string_format_na(self): '4 4.0 bar') assert result == expected + def test_to_string_format_inf(self): + # Issue #24861 + tm.reset_display_options() + df = DataFrame({ + 'A': [-np.inf, np.inf, -1, -2.1234, 3, 4], + 'B': [-np.inf, np.inf, 'foo', 'foooo', 'fooooo', 'bar'] + }) + result = df.to_string() + + expected = (' A B\n' + '0 -inf -inf\n' + '1 inf inf\n' + '2 -1.0000 foo\n' + '3 -2.1234 foooo\n' + '4 3.0000 fooooo\n' + '5 4.0000 bar') + assert result == expected + + df = DataFrame({ + 'A': [-np.inf, np.inf, -1., -2., 3., 4.], + 'B': [-np.inf, np.inf, 'foo', 'foooo', 'fooooo', 'bar'] + }) + result = df.to_string() + + expected = (' A B\n' + '0 -inf -inf\n' + '1 inf inf\n' + '2 -1.0 foo\n' + '3 -2.0 foooo\n' + '4 3.0 fooooo\n' + '5 4.0 bar') + assert result == expected + def test_to_string_decimal(self): # Issue #23614 df = DataFrame({'A': [6.0, 3.1, 2.2]}) From f38db6d17bf6ca0fbb92df1698cc26d25d246d69 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Mon, 21 Jan 2019 17:34:13 +0100 Subject: [PATCH 2/3] PEP8 --- pandas/io/formats/format.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/format.py b/pandas/io/formats/format.py index f8a739177a1ae..2c1fcab1ebde9 100644 --- a/pandas/io/formats/format.py +++ b/pandas/io/formats/format.py @@ -1415,7 +1415,7 @@ def _trim_zeros(str_floats, na_rep='NaN'): trimmed = str_floats def _is_number(x): - return (x != na_rep and not x.endswith('inf')) + return (x != na_rep and not x.endswith('inf')) def _cond(values): finite = [x for x in values if _is_number(x)] From e19321b185bb021aa069ff235c3d659d9cd34a5b Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Wed, 23 Jan 2019 11:37:57 +0100 Subject: [PATCH 3/3] Add entry in whats new --- doc/source/whatsnew/v0.24.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v0.24.0.rst b/doc/source/whatsnew/v0.24.0.rst index 69b59793f7c0d..6787022ba295c 100644 --- a/doc/source/whatsnew/v0.24.0.rst +++ b/doc/source/whatsnew/v0.24.0.rst @@ -1751,6 +1751,7 @@ I/O - Bug in :meth:`DataFrame.to_stata`, :class:`pandas.io.stata.StataWriter` and :class:`pandas.io.stata.StataWriter117` where a exception would leave a partially written and invalid dta file (:issue:`23573`) - Bug in :meth:`DataFrame.to_stata` and :class:`pandas.io.stata.StataWriter117` that produced invalid files when using strLs with non-ASCII characters (:issue:`23573`) - Bug in :class:`HDFStore` that caused it to raise ``ValueError`` when reading a Dataframe in Python 3 from fixed format written in Python 2 (:issue:`24510`) +- Bug in :func:`DataFrame.to_string()` and more generally in the floating ``repr`` formatter. Zeros were not trimmed if ``inf`` was present in a columns while it was the case with NA values. Zeros are now trimmed as in the presence of NA (:issue:`24861`). Plotting ^^^^^^^^