diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 432dd46000eb3..62f1d9aef3e13 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -35,6 +35,7 @@ Other enhancements - Additional options added to :meth:`.Styler.bar` to control alignment and display, with keyword only arguments (:issue:`26070`, :issue:`36419`) - :meth:`Styler.bar` now validates the input argument ``width`` and ``height`` (:issue:`42511`) - :meth:`Series.ewm`, :meth:`DataFrame.ewm`, now support a ``method`` argument with a ``'table'`` option that performs the windowing operation over an entire :class:`DataFrame`. See :ref:`Window Overview ` for performance and functional benefits (:issue:`42273`) +- Added ``sparse_index`` and ``sparse_columns`` keyword arguments to :meth:`.Styler.to_html` (:issue:`41946`) - Added keyword argument ``environment`` to :meth:`.Styler.to_latex` also allowing a specific "longtable" entry with a separate jinja2 template (:issue:`41866`) - diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 9dade82e9809c..af1c0ca34ec0f 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -476,8 +476,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. @@ -815,6 +815,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, @@ -840,6 +842,18 @@ 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. + + .. 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. @@ -866,8 +880,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, diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 4e71cb4c46626..2657370bf8258 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -6,6 +6,7 @@ from pandas import ( DataFrame, MultiIndex, + option_context, ) jinja2 = pytest.importorskip("jinja2") @@ -429,3 +430,24 @@ def test_sticky_levels(styler_mi, index, columns): def test_sticky_raises(styler): with pytest.raises(ValueError, match="`axis` must be"): styler.set_sticky(axis="bad") + + +@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 + + 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