From 9040b98d52ed77006ef87b5dcd75356b800e8b89 Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Thu, 28 Mar 2019 14:10:28 -0700 Subject: [PATCH 1/7] BUG-17280 to_html follows display.precision for column numbers --- doc/source/whatsnew/v0.25.0.rst | 1 + pandas/io/formats/html.py | 9 ++++++++- pandas/tests/io/formats/test_to_html.py | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.25.0.rst b/doc/source/whatsnew/v0.25.0.rst index c7554a70bea91..3a0063a0aca09 100644 --- a/doc/source/whatsnew/v0.25.0.rst +++ b/doc/source/whatsnew/v0.25.0.rst @@ -353,6 +353,7 @@ I/O - Bug in :meth:`DataFrame.to_string` and :meth:`DataFrame.to_latex` that would lead to incorrect output when the ``header`` keyword is used (:issue:`16718`) - Bug in :func:`read_csv` not properly interpreting the UTF8 encoded filenames on Windows on Python 3.6+ (:issue:`15086`) - Improved performance in :meth:`pandas.read_stata` and :class:`pandas.io.stata.StataReader` when converting columns that have missing values (:issue:`25772`) +- Bug in :meth:`DataFrame.to_html` where header numbers would ignore display options when rounding (:issue:`17280`) Plotting diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 6ba24a95032f8..ca38dcf997052 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -292,7 +292,14 @@ def _write_col_header(self, indent): row.append(self.columns.name or '') else: row.append('') - row.extend(self.columns) + + precision = get_option('display.precision') + for column in self.columns: + if isinstance(column, float): + row.append('{float:.{precision}f}' + .format(float=column, precision=precision)) + else: + row.append(column) align = self.fmt.justify if truncate_h: diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 148a42a332661..d8e5090241f75 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -633,3 +633,11 @@ def test_to_html_invalid_classes_type(classes): with pytest.raises(TypeError, match=msg): df.to_html(classes=classes) + + +@pytest.mark.parametrize("notebook", [True, False]) +def test_to_html_round_column_headers(notebook): + df = DataFrame([1], columns=[0.55555555]) + with pd.option_context('display.precision', 3): + html = df.to_html(notebook=notebook) + assert "0.556" in html From 21d8273f8cfb082134712c48ff8076012a28eecf Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Thu, 28 Mar 2019 19:34:57 -0700 Subject: [PATCH 2/7] applies to notebooks only --- pandas/io/formats/html.py | 17 ++++++++++------- pandas/tests/io/formats/test_to_html.py | 11 ++++++----- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index ca38dcf997052..f605c03b068fd 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -293,13 +293,7 @@ def _write_col_header(self, indent): else: row.append('') - precision = get_option('display.precision') - for column in self.columns: - if isinstance(column, float): - row.append('{float:.{precision}f}' - .format(float=column, precision=precision)) - else: - row.append(column) + row.extend(self.columns) align = self.fmt.justify if truncate_h: @@ -497,6 +491,15 @@ class NotebookFormatter(HTMLFormatter): Notebooks. This class is intended for functionality specific to DataFrame._repr_html_() and DataFrame.to_html(notebook=True) """ + + def __init__(self, formatter, classes=None, border=None): + super(NotebookFormatter, self).__init__(formatter, + classes=classes, + border=border) + precision = get_option('display.precision') + fmt = lambda f: '{float:.{p}f}'.format(float=f, p=precision) + fmt_floats = lambda f: fmt(f) if isinstance(f, float) else f + self.columns = self.columns.map(fmt_floats) def _get_formatted_values(self): return {i: self.fmt._format_col(i) for i in range(self.ncols)} diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index d8e5090241f75..6b0487d239d4a 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -635,9 +635,10 @@ def test_to_html_invalid_classes_type(classes): df.to_html(classes=classes) -@pytest.mark.parametrize("notebook", [True, False]) -def test_to_html_round_column_headers(notebook): - df = DataFrame([1], columns=[0.55555555]) +def test_to_html_round_column_headers(): + df = DataFrame([1], columns=[0.55555]) with pd.option_context('display.precision', 3): - html = df.to_html(notebook=notebook) - assert "0.556" in html + html = df.to_html(notebook=False) + notebook = df.to_html(notebook=True) + assert "0.55555" in html + assert "0.556" in notebook From 8e0b7ee09a4ecca583f838b6e3497de619766b22 Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Thu, 28 Mar 2019 19:36:03 -0700 Subject: [PATCH 3/7] fix whitespace --- pandas/io/formats/html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index f605c03b068fd..66bcba0dddd5e 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -491,7 +491,7 @@ class NotebookFormatter(HTMLFormatter): Notebooks. This class is intended for functionality specific to DataFrame._repr_html_() and DataFrame.to_html(notebook=True) """ - + def __init__(self, formatter, classes=None, border=None): super(NotebookFormatter, self).__init__(formatter, classes=classes, From 87c183e766be599e9c0c09fd344559be22d50ec3 Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Thu, 28 Mar 2019 20:03:05 -0700 Subject: [PATCH 4/7] fix whitespace --- pandas/io/formats/html.py | 1 - 1 file changed, 1 deletion(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 66bcba0dddd5e..2b399377f9fea 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -292,7 +292,6 @@ def _write_col_header(self, indent): row.append(self.columns.name or '') else: row.append('') - row.extend(self.columns) align = self.fmt.justify From f7d80863df65becb66e0e257926c92450ec43d00 Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Fri, 29 Mar 2019 09:56:01 -0700 Subject: [PATCH 5/7] move formatting to _get_columns_formatted_values function --- pandas/io/formats/html.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 2b399377f9fea..5ec5ef010fd3c 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -36,7 +36,7 @@ def __init__(self, formatter, classes=None, border=None): self.classes = classes self.frame = self.fmt.frame - self.columns = self.fmt.tr_frame.columns + self.columns = self._get_columns_formatted_values() self.elements = [] self.bold_rows = self.fmt.kwds.get('bold_rows', False) self.escape = self.fmt.kwds.get('escape', True) @@ -70,6 +70,9 @@ def row_levels(self): # not showing (row) index return 0 + def _get_columns_formatted_values(self): + return self.fmt.tr_frame.columns + @property def is_truncated(self): return self.fmt.is_truncated @@ -495,14 +498,17 @@ def __init__(self, formatter, classes=None, border=None): super(NotebookFormatter, self).__init__(formatter, classes=classes, border=border) - precision = get_option('display.precision') - fmt = lambda f: '{float:.{p}f}'.format(float=f, p=precision) - fmt_floats = lambda f: fmt(f) if isinstance(f, float) else f - self.columns = self.columns.map(fmt_floats) + self.columns = self._get_columns_formatted_values() def _get_formatted_values(self): return {i: self.fmt._format_col(i) for i in range(self.ncols)} + def _get_columns_formatted_values(self): + precision = get_option('display.precision') + fmt = lambda f: '{float:.{p}f}'.format(float=f, p=precision) + fmt_floats = lambda f: fmt(f) if isinstance(f, float) else f + return self.fmt.tr_frame.columns.map(fmt_floats) + def write_style(self): # We use the "scoped" attribute here so that the desired # style properties for the data frame are not then applied From 50aea27625edab08508835097b529ed37a1c6002 Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Tue, 2 Apr 2019 23:42:42 -0700 Subject: [PATCH 6/7] use self.columns.format() --- pandas/io/formats/html.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 5ec5ef010fd3c..358dc8d50d09d 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -36,7 +36,7 @@ def __init__(self, formatter, classes=None, border=None): self.classes = classes self.frame = self.fmt.frame - self.columns = self._get_columns_formatted_values() + self.columns = self.fmt.tr_frame.columns self.elements = [] self.bold_rows = self.fmt.kwds.get('bold_rows', False) self.escape = self.fmt.kwds.get('escape', True) @@ -295,7 +295,7 @@ def _write_col_header(self, indent): row.append(self.columns.name or '') else: row.append('') - row.extend(self.columns) + row.extend(self._get_columns_formatted_values()) align = self.fmt.justify if truncate_h: @@ -494,20 +494,11 @@ class NotebookFormatter(HTMLFormatter): DataFrame._repr_html_() and DataFrame.to_html(notebook=True) """ - def __init__(self, formatter, classes=None, border=None): - super(NotebookFormatter, self).__init__(formatter, - classes=classes, - border=border) - self.columns = self._get_columns_formatted_values() - def _get_formatted_values(self): return {i: self.fmt._format_col(i) for i in range(self.ncols)} def _get_columns_formatted_values(self): - precision = get_option('display.precision') - fmt = lambda f: '{float:.{p}f}'.format(float=f, p=precision) - fmt_floats = lambda f: fmt(f) if isinstance(f, float) else f - return self.fmt.tr_frame.columns.map(fmt_floats) + return self.columns.format() def write_style(self): # We use the "scoped" attribute here so that the desired From 4ea193228c85ba529d59a320cbbdd7725ecae05c Mon Sep 17 00:00:00 2001 From: JustinZhengBC Date: Wed, 3 Apr 2019 08:22:51 -0700 Subject: [PATCH 7/7] add issue number --- pandas/io/formats/html.py | 2 +- pandas/tests/io/formats/test_to_html.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/html.py b/pandas/io/formats/html.py index 358dc8d50d09d..17b7b7f175e71 100644 --- a/pandas/io/formats/html.py +++ b/pandas/io/formats/html.py @@ -71,7 +71,7 @@ def row_levels(self): return 0 def _get_columns_formatted_values(self): - return self.fmt.tr_frame.columns + return self.columns @property def is_truncated(self): diff --git a/pandas/tests/io/formats/test_to_html.py b/pandas/tests/io/formats/test_to_html.py index 6b0487d239d4a..a5a96866b5d24 100644 --- a/pandas/tests/io/formats/test_to_html.py +++ b/pandas/tests/io/formats/test_to_html.py @@ -636,6 +636,7 @@ def test_to_html_invalid_classes_type(classes): def test_to_html_round_column_headers(): + # GH 17280 df = DataFrame([1], columns=[0.55555]) with pd.option_context('display.precision', 3): html = df.to_html(notebook=False)