From c3364793bda2fbb87c03d49ff5ad18cf03e8ff3d Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Mon, 20 Sep 2021 21:20:16 +0200 Subject: [PATCH 1/5] ENH: omit CSSStyle rules for hidden table cells (#43619) --- doc/source/whatsnew/v1.3.4.rst | 7 ++-- pandas/io/formats/style_render.py | 7 ++-- pandas/tests/io/formats/style/test_html.py | 39 ++++++++++++++++++++++ 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/doc/source/whatsnew/v1.3.4.rst b/doc/source/whatsnew/v1.3.4.rst index daefa9dc618f5..c27f54c92e1f9 100644 --- a/doc/source/whatsnew/v1.3.4.rst +++ b/doc/source/whatsnew/v1.3.4.rst @@ -33,10 +33,9 @@ Bug fixes .. _whatsnew_134.other: -Other -~~~~~ -- -- +Performance improvements +~~~~~~~~~~~~~~~~~~~~~~~~ +- Performance improvement in :meth:`Styler.to_html` by omitting CSSStyle rules for hidden table cells (:issue:`43619`) .. --------------------------------------------------------------------------- diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 0ec6a9b470b50..76e79b12c36b2 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -580,18 +580,21 @@ def _translate_body( if (r, c) in self.cell_context: cls = " " + self.cell_context[r, c] + data_element_is_visible = ( + c not in self.hidden_columns and r not in self.hidden_rows + ) data_element = _element( "td", f"{data_class} row{r} col{c}{cls}", value, - (c not in self.hidden_columns and r not in self.hidden_rows), + data_element_is_visible, attributes="", display_value=self._display_funcs[(r, c)](value), ) if self.cell_ids: data_element["id"] = f"row{r}_col{c}" - if (r, c) in self.ctx and self.ctx[r, c]: + if data_element_is_visible and (r, c) in self.ctx and self.ctx[r, c]: # always add id if needed due to specified style data_element["id"] = f"row{r}_col{c}" self.cellstyle_map[tuple(self.ctx[r, c])].append(f"row{r}_col{c}") diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index bbb81e2dce24e..e7877ceefa083 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -467,3 +467,42 @@ def test_maximums(styler_mi, rows, cols): assert ">5" in result # [[0,1], [4,5]] always visible assert (">8" in result) is not rows # first trimmed vertical element assert (">2" in result) is not cols # first trimmed horizontal element + + +def test_omit_css_style_rules_for_hidden_cells(): + # GH 43619 + df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) + result = ( + df.style.set_uuid("") + .background_gradient() + .hide_columns(["A"]) + .hide_index([0]) + .to_html() + ) + expected = dedent( + """\ + + + + + + + + + + + + + + + + +
 B
14
+ """ + ) + assert result == expected From 394e436b77916ba2e1f421e79b34176963e70aff Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 21 Sep 2021 12:16:30 +0200 Subject: [PATCH 2/5] simplify test - use fixture - test only styles - use "applymap" instead of "background_gradient" --- pandas/tests/io/formats/style/test_html.py | 36 ++++++---------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index e7877ceefa083..d60d15f8d7c23 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -469,40 +469,22 @@ def test_maximums(styler_mi, rows, cols): assert (">2" in result) is not cols # first trimmed horizontal element -def test_omit_css_style_rules_for_hidden_cells(): +def test_include_css_style_rules_only_for_visible_cells(styler_mi): # GH 43619 - df = DataFrame([[1, 2], [3, 4]], columns=["A", "B"]) result = ( - df.style.set_uuid("") - .background_gradient() - .hide_columns(["A"]) - .hide_index([0]) + styler_mi.set_uuid("") + .applymap(lambda v: "color: blue;") + .hide_columns(styler_mi.data.columns[1:]) + .hide_index(styler_mi.data.index[1:]) .to_html() ) - expected = dedent( + expected_styles = dedent( """\ - - - - - - - - - - - - - - - -
 B
14
""" ) - assert result == expected + assert expected_styles in result From 3566aee9210f25369aac7ba70d79ef2f5b1f55d0 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 21 Sep 2021 12:19:44 +0200 Subject: [PATCH 3/5] omit CSSStyle rules for hidden index labels --- pandas/io/formats/style_render.py | 17 ++++++++++++----- pandas/tests/io/formats/style/test_html.py | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 76e79b12c36b2..9e5e532f8dce7 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -537,11 +537,14 @@ def _translate_body( index_headers = [] for c, value in enumerate(rlabels[r]): + header_element_visible = ( + _is_visible(r, c, idx_lengths) and not self.hide_index_[c] + ) header_element = _element( "th", f"{row_heading_class} level{c} row{r}", value, - _is_visible(r, c, idx_lengths) and not self.hide_index_[c], + header_element_visible, display_value=self._display_funcs_index[(r, c)](value), attributes=( f'rowspan="{idx_lengths.get((c, r), 0)}"' @@ -552,7 +555,11 @@ def _translate_body( if self.cell_ids: header_element["id"] = f"level{c}_row{r}" # id is specified - if (r, c) in self.ctx_index and self.ctx_index[r, c]: + if ( + header_element_visible + and (r, c) in self.ctx_index + and self.ctx_index[r, c] + ): # always add id if a style is specified header_element["id"] = f"level{c}_row{r}" self.cellstyle_map_index[tuple(self.ctx_index[r, c])].append( @@ -580,21 +587,21 @@ def _translate_body( if (r, c) in self.cell_context: cls = " " + self.cell_context[r, c] - data_element_is_visible = ( + data_element_visible = ( c not in self.hidden_columns and r not in self.hidden_rows ) data_element = _element( "td", f"{data_class} row{r} col{c}{cls}", value, - data_element_is_visible, + data_element_visible, attributes="", display_value=self._display_funcs[(r, c)](value), ) if self.cell_ids: data_element["id"] = f"row{r}_col{c}" - if data_element_is_visible and (r, c) in self.ctx and self.ctx[r, c]: + if data_element_visible and (r, c) in self.ctx and self.ctx[r, c]: # always add id if needed due to specified style data_element["id"] = f"row{r}_col{c}" self.cellstyle_map[tuple(self.ctx[r, c])].append(f"row{r}_col{c}") diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index d60d15f8d7c23..9f967b0f9eb3b 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -488,3 +488,24 @@ def test_include_css_style_rules_only_for_visible_cells(styler_mi): """ ) assert expected_styles in result + + +def test_include_css_style_rules_only_for_visible_index_labels(styler_mi): + # GH 43619 + result = ( + styler_mi.set_uuid("") + .applymap_index(lambda v: "color: blue;", axis="index") + .hide_columns(styler_mi.data.columns) + .hide_index(styler_mi.data.index[1:]) + .to_html() + ) + expected_styles = dedent( + """\ + + """ + ) + assert expected_styles in result From eddea068280fc0cc662978ba67683041d5948fc5 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 21 Sep 2021 12:30:16 +0200 Subject: [PATCH 4/5] omit CSSStyle rules for hidden column labels --- pandas/io/formats/style_render.py | 9 +++++++-- pandas/tests/io/formats/style/test_html.py | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 9e5e532f8dce7..9f12694cc3b21 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -378,11 +378,12 @@ def _translate_header( if clabels: column_headers = [] for c, value in enumerate(clabels[r]): + header_element_visible = _is_visible(c, r, col_lengths) header_element = _element( "th", f"{col_heading_class} level{r} col{c}", value, - _is_visible(c, r, col_lengths), + header_element_visible, display_value=self._display_funcs_columns[(r, c)](value), attributes=( f'colspan="{col_lengths.get((r, c), 0)}"' @@ -393,7 +394,11 @@ def _translate_header( if self.cell_ids: header_element["id"] = f"level{r}_col{c}" - if (r, c) in self.ctx_columns and self.ctx_columns[r, c]: + if ( + header_element_visible + and (r, c) in self.ctx_columns + and self.ctx_columns[r, c] + ): header_element["id"] = f"level{r}_col{c}" self.cellstyle_map_columns[ tuple(self.ctx_columns[r, c]) diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 9f967b0f9eb3b..b37edf1c09cd1 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -509,3 +509,24 @@ def test_include_css_style_rules_only_for_visible_index_labels(styler_mi): """ ) assert expected_styles in result + + +def test_include_css_style_rules_only_for_visible_column_labels(styler_mi): + # GH 43619 + result = ( + styler_mi.set_uuid("") + .applymap_index(lambda v: "color: blue;", axis="columns") + .hide_columns(styler_mi.data.columns[1:]) + .hide_index(styler_mi.data.index) + .to_html() + ) + expected_styles = dedent( + """\ + + """ + ) + assert expected_styles in result From fe9e44b9586a117fe1904a0f3d80f2299ce43e29 Mon Sep 17 00:00:00 2001 From: Daniel Schmidt Date: Tue, 21 Sep 2021 12:31:00 +0200 Subject: [PATCH 5/5] move "whatsnew entry" to "1.4.0" release notes --- doc/source/whatsnew/v1.3.4.rst | 7 ++++--- doc/source/whatsnew/v1.4.0.rst | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/source/whatsnew/v1.3.4.rst b/doc/source/whatsnew/v1.3.4.rst index c27f54c92e1f9..daefa9dc618f5 100644 --- a/doc/source/whatsnew/v1.3.4.rst +++ b/doc/source/whatsnew/v1.3.4.rst @@ -33,9 +33,10 @@ Bug fixes .. _whatsnew_134.other: -Performance improvements -~~~~~~~~~~~~~~~~~~~~~~~~ -- Performance improvement in :meth:`Styler.to_html` by omitting CSSStyle rules for hidden table cells (:issue:`43619`) +Other +~~~~~ +- +- .. --------------------------------------------------------------------------- diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index f18b3b75ca3d2..88f1a19eda7fe 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -79,6 +79,7 @@ Styler - Keyword arguments ``level`` and ``names`` added to :meth:`.Styler.hide_index` and :meth:`.Styler.hide_columns` for additional control of visibility of MultiIndexes and index names (:issue:`25475`, :issue:`43404`, :issue:`43346`) - Global options have been extended to configure default ``Styler`` properties including formatting and encoding and mathjax options and LaTeX (:issue:`41395`) - Naive sparsification is now possible for LaTeX without the multirow package (:issue:`43369`) + - :meth:`Styler.to_html` omits CSSStyle rules for hidden table elements (:issue:`43619`) Formerly Styler relied on ``display.html.use_mathjax``, which has now been replaced by ``styler.html.mathjax``.