Skip to content

Commit 66cec77

Browse files
committed
BUG: display.precision options seems off-by-one (GH10451)
1 parent e13739a commit 66cec77

File tree

5 files changed

+62
-13
lines changed

5 files changed

+62
-13
lines changed

doc/source/options.rst

+6-4
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ can specify the option ``df.info(null_counts=True)`` to override on showing a pa
227227
df.info()
228228
pd.reset_option('max_info_rows')
229229
230-
``display.precision`` sets the output display precision. This is only a
230+
``display.precision`` sets the output display precision in terms of decimal places. This is only a
231231
suggestion.
232232

233233
.. ipython:: python
@@ -368,9 +368,11 @@ display.notebook_repr_html True When True, IPython notebook will
368368
pandas objects (if it is available).
369369
display.pprint_nest_depth 3 Controls the number of nested levels
370370
to process when pretty-printing
371-
display.precision 7 Floating point output precision
372-
(number of significant digits). This is
373-
only a suggestion
371+
display.precision 6 Floating point output precision in
372+
terms of number of places after the
373+
decimal, for regular formatting as well
374+
as scientific notation. Similar to
375+
numpy's ``precision`` print option
374376
display.show_dimensions truncate Whether to print out dimensions
375377
at the end of DataFrame repr.
376378
If 'truncate' is specified, only

doc/source/whatsnew/v0.17.0.txt

+36
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,42 @@ New behavior:
391391

392392
See :ref:`documentation <io.hdf5>` for more details.
393393

394+
Changes to ``display.precision`` option
395+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
396+
397+
The ``display.precision`` option has been clarified to refer to decimal places (:issue:`10451`).
398+
399+
Earlier versions of pandas would format floating point numbers to have one less decimal place than the value in
400+
``display.precision``.
401+
402+
.. code-block:: python
403+
404+
In [1]: pd.set_option('display.precision', 2)
405+
406+
In [2]: pd.DataFrame({'x': [123.456789]})
407+
Out[2]:
408+
x
409+
0 123.5
410+
411+
If interpreting precision as "significant figures" this did work for scientific notation but that same interpretation
412+
did not work for values with standard formatting. It was also out of step with how numpy handles formatting.
413+
414+
Going forward the value of ``display.precision`` will directly control the number of places after the decimal, for
415+
regular formatting as well as scientific notation, similar to how numpy's ``precision`` print option works.
416+
417+
.. ipython:: python
418+
419+
pd.set_option('display.precision', 2)
420+
pd.DataFrame({'x': [123.456789]})
421+
422+
To preserve output behavior with prior versions the default value of ``display.precision`` has been reduced to ``6``
423+
from ``7``.
424+
425+
.. ipython:: python
426+
:suppress:
427+
pd.set_option('display.precision', 6)
428+
429+
394430
.. _whatsnew_0170.api_breaking.other:
395431

396432
Other API Changes

pandas/core/config_init.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ def mpl_style_cb(key):
236236
return val
237237

238238
with cf.config_prefix('display'):
239-
cf.register_option('precision', 7, pc_precision_doc, validator=is_int)
239+
cf.register_option('precision', 6, pc_precision_doc, validator=is_int)
240240
cf.register_option('float_format', None, float_format_doc)
241241
cf.register_option('column_space', 12, validator=is_int)
242242
cf.register_option('max_info_rows', 1690785, pc_max_info_rows_doc,

pandas/core/format.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -2014,28 +2014,28 @@ def _format_strings(self):
20142014
if self.formatter is not None:
20152015
fmt_values = [self.formatter(x) for x in self.values]
20162016
else:
2017-
fmt_str = '%% .%df' % (self.digits - 1)
2017+
fmt_str = '%% .%df' % self.digits
20182018
fmt_values = self._format_with(fmt_str)
20192019

20202020
if len(fmt_values) > 0:
20212021
maxlen = max(len(x) for x in fmt_values)
20222022
else:
20232023
maxlen = 0
20242024

2025-
too_long = maxlen > self.digits + 5
2025+
too_long = maxlen > self.digits + 6
20262026

20272027
abs_vals = np.abs(self.values)
20282028

20292029
# this is pretty arbitrary for now
20302030
has_large_values = (abs_vals > 1e8).any()
2031-
has_small_values = ((abs_vals < 10 ** (-self.digits+1)) &
2031+
has_small_values = ((abs_vals < 10 ** (-self.digits)) &
20322032
(abs_vals > 0)).any()
20332033

20342034
if too_long and has_large_values:
2035-
fmt_str = '%% .%de' % (self.digits - 1)
2035+
fmt_str = '%% .%de' % self.digits
20362036
fmt_values = self._format_with(fmt_str)
20372037
elif has_small_values:
2038-
fmt_str = '%% .%de' % (self.digits - 1)
2038+
fmt_str = '%% .%de' % self.digits
20392039
fmt_values = self._format_with(fmt_str)
20402040

20412041
return fmt_values

pandas/tests/test_format.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,7 @@ def test_to_string_no_index(self):
15231523

15241524
def test_to_string_float_formatting(self):
15251525
self.reset_display_options()
1526-
fmt.set_option('display.precision', 6, 'display.column_space',
1526+
fmt.set_option('display.precision', 5, 'display.column_space',
15271527
12, 'display.notebook_repr_html', False)
15281528

15291529
df = DataFrame({'x': [0, 0.25, 3456.000, 12e+45, 1.64e+6,
@@ -1554,7 +1554,7 @@ def test_to_string_float_formatting(self):
15541554
self.assertEqual(df_s, expected)
15551555

15561556
self.reset_display_options()
1557-
self.assertEqual(get_option("display.precision"), 7)
1557+
self.assertEqual(get_option("display.precision"), 6)
15581558

15591559
df = DataFrame({'x': [1e9, 0.2512]})
15601560
df_s = df.to_string()
@@ -3055,7 +3055,7 @@ def test_output_significant_digits(self):
30553055
# Issue #9764
30563056

30573057
# In case default display precision changes:
3058-
with pd.option_context('display.precision', 7):
3058+
with pd.option_context('display.precision', 6):
30593059
# DataFrame example from issue #9764
30603060
d=pd.DataFrame({'col1':[9.999e-8, 1e-7, 1.0001e-7, 2e-7, 4.999e-7, 5e-7, 5.0001e-7, 6e-7, 9.999e-7, 1e-6, 1.0001e-6, 2e-6, 4.999e-6, 5e-6, 5.0001e-6, 6e-6]})
30613061

@@ -3070,6 +3070,17 @@ def test_output_significant_digits(self):
30703070
for (start, stop), v in expected_output.items():
30713071
self.assertEqual(str(d[start:stop]), v)
30723072

3073+
def test_too_long(self):
3074+
# GH 10451
3075+
with pd.option_context('display.precision', 4):
3076+
# need both a number > 1e8 and something that normally formats to having length > display.precision + 6
3077+
df = pd.DataFrame(dict(x=[12345.6789]))
3078+
self.assertEqual(str(df), ' x\n0 12345.6789')
3079+
df = pd.DataFrame(dict(x=[2e8]))
3080+
self.assertEqual(str(df), ' x\n0 200000000')
3081+
df = pd.DataFrame(dict(x=[12345.6789, 2e8]))
3082+
self.assertEqual(str(df), ' x\n0 1.2346e+04\n1 2.0000e+08')
3083+
30733084

30743085
class TestRepr_timedelta64(tm.TestCase):
30753086

0 commit comments

Comments
 (0)