From be1596790408b0317649a69717abb3858a52eb1e Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Fri, 11 Jun 2021 10:52:39 +0200 Subject: [PATCH 1/6] add sparsify to to_html --- pandas/io/formats/style.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 93c3843b36846..3e60ab3097ba5 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -750,6 +750,8 @@ def to_html( *, table_uuid: str | None = None, table_attributes: str | None = None, + sparse_index: bool | None = None, + sparse_columns: bool | None = None, encoding: str | None = None, doctype_html: bool = False, exclude_styles: bool = False, @@ -775,6 +777,14 @@ def to_html( `` >`` If not given defaults to Styler's preexisting value. + sparse_index : bool, optional + Whether to sparsify the display of a hierarchical index. Setting to False + will display each explicit level element in a hierarchical key for each row. + Defaults to ``pandas.options.styler.sparse.index`` value. + sparse_columns : bool, optional + Whether to sparsify the display of a hierarchical index. Setting to False + will display each explicit level element in a hierarchical key for each row. + Defaults to ``pandas.options.styler.sparse.columns`` value. encoding : str, optional Character encoding setting for file output, and HTML meta tags, defaults to "utf-8" if None. @@ -801,8 +811,15 @@ def to_html( if table_attributes: self.set_table_attributes(table_attributes) + if sparse_index is None: + sparse_index = get_option("styler.sparse.index") + if sparse_columns is None: + sparse_columns = get_option("styler.sparse.columns") + # Build HTML string.. - html = self.render( + html = self._render_html( + sparse_index=sparse_index, + sparse_columns=sparse_columns, exclude_styles=exclude_styles, encoding=encoding if encoding else "utf-8", doctype_html=doctype_html, From c187dc2367fc4e7877fbd41ae5867ed881d4dbb2 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Fri, 11 Jun 2021 11:48:36 +0200 Subject: [PATCH 2/6] add tests --- pandas/tests/io/formats/style/test_html.py | 31 +++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 74b4c7ea3977c..84a331c971f4d 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -2,7 +2,11 @@ import pytest -from pandas import DataFrame +from pandas import ( + DataFrame, + MultiIndex, + option_context, +) jinja2 = pytest.importorskip("jinja2") from pandas.io.formats.style import Styler @@ -236,3 +240,28 @@ def test_from_custom_template(tmpdir): def test_caption_as_sequence(styler): styler.set_caption(("full cap", "short cap")) assert "" in styler.render() + + +def test_sparse_options(): + cidx = MultiIndex.from_tuples([("Z", "a"), ("Z", "b"), ("Y", "c")]) + ridx = MultiIndex.from_tuples([("A", "a"), ("A", "b"), ("B", "c")]) + df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], index=ridx, columns=cidx) + styler = df.style + + base_html = styler.to_html() + + # test option context and method arguments simultaneously + # output generation is tested in test_style.test_mi_sparse + for sparse_index in [True, False]: + with option_context("styler.sparse.index", sparse_index): + html1 = styler.to_html() + assert (html1 == base_html) is sparse_index + html2 = styler.to_html(sparse_index=sparse_index, sparse_columns=True) + assert html1 == html2 + + for sparse_columns in [True, False]: + with option_context("styler.sparse.columns", sparse_columns): + html1 = styler.to_html() + assert (html1 == base_html) is sparse_columns + html2 = styler.to_html(sparse_index=True, sparse_columns=sparse_columns) + assert html1 == html2 From c53040ed2db24208f516889c9125accffdb234fa Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Fri, 11 Jun 2021 11:54:53 +0200 Subject: [PATCH 3/6] doc fix --- pandas/io/formats/style.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 3e60ab3097ba5..d476f4ec2b901 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -470,8 +470,8 @@ def to_latex( Defaults to ``pandas.options.styler.sparse.index`` value. sparse_columns : bool, optional Whether to sparsify the display of a hierarchical index. Setting to False - will display each explicit level element in a hierarchical key for each row. - Defaults to ``pandas.options.styler.sparse.columns`` value. + will display each explicit level element in a hierarchical key for each + column. Defaults to ``pandas.options.styler.sparse.columns`` value. multirow_align : {"c", "t", "b"} If sparsifying hierarchical MultiIndexes whether to align text centrally, at the top or bottom. @@ -783,8 +783,8 @@ def to_html( Defaults to ``pandas.options.styler.sparse.index`` value. sparse_columns : bool, optional Whether to sparsify the display of a hierarchical index. Setting to False - will display each explicit level element in a hierarchical key for each row. - Defaults to ``pandas.options.styler.sparse.columns`` value. + will display each explicit level element in a hierarchical key for each + column. Defaults to ``pandas.options.styler.sparse.columns`` value. encoding : str, optional Character encoding setting for file output, and HTML meta tags, defaults to "utf-8" if None. From 512af500ba1b6201b350f7b4cd60bd44c8f783bc Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 5 Jul 2021 09:24:13 +0200 Subject: [PATCH 4/6] whats new 1.4.0 --- doc/source/whatsnew/v1.4.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 764a50e13586a..c5249bfd0276a 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -30,7 +30,7 @@ enhancement2 Other enhancements ^^^^^^^^^^^^^^^^^^ - :meth:`Series.sample`, :meth:`DataFrame.sample`, and :meth:`.GroupBy.sample` now accept a ``np.random.Generator`` as input to ``random_state``. A generator will be more performant, especially with ``replace=False`` (:issue:`38100`) -- +- Added ``sparse_index`` and ``sparse_columns`` keyword arguments to :meth:`.Styler.to_html` (:issue:`41946`) .. --------------------------------------------------------------------------- From 13090ab93c2c18f8a0775db8bbfaa3e5e4ea3886 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 5 Jul 2021 09:37:29 +0200 Subject: [PATCH 5/6] better test --- pandas/tests/io/formats/style/test_html.py | 32 ++++++++++------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 9e5f429a47239..451f53936d9e0 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -414,26 +414,22 @@ def test_sticky_raises(styler): styler.set_sticky(axis="bad") -def test_sparse_options(): +@pytest.mark.parametrize( + "sparse_index, sparse_columns", + [(True, True), (True, False), (False, True), (False, False)], +) +def test_sparse_options(sparse_index, sparse_columns): cidx = MultiIndex.from_tuples([("Z", "a"), ("Z", "b"), ("Y", "c")]) ridx = MultiIndex.from_tuples([("A", "a"), ("A", "b"), ("B", "c")]) df = DataFrame([[1, 2, 3], [4, 5, 6], [7, 8, 9]], index=ridx, columns=cidx) styler = df.style - base_html = styler.to_html() - - # test option context and method arguments simultaneously - # output generation is tested in test_style.test_mi_sparse - for sparse_index in [True, False]: - with option_context("styler.sparse.index", sparse_index): - html1 = styler.to_html() - assert (html1 == base_html) is sparse_index - html2 = styler.to_html(sparse_index=sparse_index, sparse_columns=True) - assert html1 == html2 - - for sparse_columns in [True, False]: - with option_context("styler.sparse.columns", sparse_columns): - html1 = styler.to_html() - assert (html1 == base_html) is sparse_columns - html2 = styler.to_html(sparse_index=True, sparse_columns=sparse_columns) - assert html1 == html2 + default_html = styler.to_html() # defaults under pd.options to (True , True) + + with option_context( + "styler.sparse.index", sparse_index, "styler.sparse.columns", sparse_columns + ): + html1 = styler.to_html() + assert (html1 == default_html) is (sparse_index and sparse_columns) + html2 = styler.to_html(sparse_index=sparse_index, sparse_columns=sparse_columns) + assert html1 == html2 From 38559f5962954245c00e338d936bd6ea3164e664 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Mon, 5 Jul 2021 09:40:02 +0200 Subject: [PATCH 6/6] versionadded --- pandas/io/formats/style.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 86ae82c93e15f..86185b46f70e6 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -830,10 +830,14 @@ def to_html( Whether to sparsify the display of a hierarchical index. Setting to False will display each explicit level element in a hierarchical key for each row. Defaults to ``pandas.options.styler.sparse.index`` value. + + .. versionadded:: 1.4.0 sparse_columns : bool, optional Whether to sparsify the display of a hierarchical index. Setting to False will display each explicit level element in a hierarchical key for each column. Defaults to ``pandas.options.styler.sparse.columns`` value. + + .. versionadded:: 1.4.0 encoding : str, optional Character encoding setting for file output, and HTML meta tags, defaults to "utf-8" if None.
full cap