diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index ba6bfb9da11cc..2f024af34b19d 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -143,7 +143,7 @@ One also has greater control of the display through separate sparsification of t Render trimming has also been added for large numbers of data elements to avoid browser overload (:issue:`40712`). We have added an extension to allow LaTeX styling as an alternative to CSS styling and a method :meth:`.Styler.to_latex` -which renders the necessary LaTeX format including built-up styles. An additional file io function :meth:`.Styler.to_html` has been added for convenience (:issue:`40312`). +which renders the necessary LaTeX format including built-up styles (:issue:`21673`, :issue:`41659`). An additional file io function :meth:`Styler.to_html` has been added for convenience (:issue:`40312`). Documentation has also seen major revisions in light of new features (:issue:`39720` :issue:`39317` :issue:`40493`) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index d6c151c3ed740..7b88d53dd7f4e 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -87,8 +87,8 @@ class Styler(StylerRenderer): List of {selector: (attr, value)} dicts; see Notes. uuid : str, default None A unique identifier to avoid CSS collisions; generated automatically. - caption : str, default None - Caption to attach to the table. + caption : str, tuple, default None + String caption to attach to the table. Tuple only used for LaTeX dual captions. table_attributes : str, default None Items that show up in the opening ```` tag in addition to automatic (by default) id. @@ -175,7 +175,7 @@ def __init__( precision: int | None = None, table_styles: CSSStyles | None = None, uuid: str | None = None, - caption: str | None = None, + caption: str | tuple | None = None, table_attributes: str | None = None, cell_ids: bool = True, na_rep: str | None = None, @@ -419,7 +419,7 @@ def to_latex( position_float: str | None = None, hrules: bool = False, label: str | None = None, - caption: str | None = None, + caption: str | tuple | None = None, sparse_index: bool | None = None, sparse_columns: bool | None = None, multirow_align: str = "c", @@ -460,8 +460,10 @@ def to_latex( label : str, optional The LaTeX label included as: \\label{
}. + caption : str, tuple, optional + If string, the LaTeX table caption included as: \\caption{}. + If tuple, i.e ("full caption", "short caption"), the caption included + as: \\caption[]{}. 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. @@ -1344,13 +1346,16 @@ def set_uuid(self, uuid: str) -> Styler: self.uuid = uuid return self - def set_caption(self, caption: str) -> Styler: + def set_caption(self, caption: str | tuple) -> Styler: """ Set the text added to a ```` HTML element. Parameters ---------- - caption : str + caption : str, tuple + For HTML output either the string input is used or the first element of the + tuple. For LaTeX the string input provides a caption and the additional + tuple input allows for full captions and short captions, in that order. Returns ------- diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 7af8802673f80..7686d8a340c37 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -75,7 +75,7 @@ def __init__( uuid_len: int = 5, table_styles: CSSStyles | None = None, table_attributes: str | None = None, - caption: str | None = None, + caption: str | tuple | None = None, cell_ids: bool = True, ): diff --git a/pandas/io/formats/templates/html_table.tpl b/pandas/io/formats/templates/html_table.tpl index dadefa4bd8365..33153af6f0882 100644 --- a/pandas/io/formats/templates/html_table.tpl +++ b/pandas/io/formats/templates/html_table.tpl @@ -6,8 +6,10 @@ {% endif %} {% block caption %} -{% if caption %} +{% if caption and caption is string %} +{% elif caption and caption is sequence %} + {% endif %} {% endblock caption %} {% block thead %} diff --git a/pandas/io/formats/templates/latex.tpl b/pandas/io/formats/templates/latex.tpl index e5db6ad8ca7f8..66fe99642850f 100644 --- a/pandas/io/formats/templates/latex.tpl +++ b/pandas/io/formats/templates/latex.tpl @@ -9,9 +9,12 @@ {% if position_float is not none%} \{{position_float}} {% endif %} -{% if caption %} +{% if caption and caption is string %} \caption{% raw %}{{% endraw %}{{caption}}{% raw %}}{% endraw %} +{% elif caption and caption is sequence %} +\caption[{{caption[1]}}]{% raw %}{{% endraw %}{{caption[0]}}{% raw %}}{% endraw %} + {% endif %} {% for style in table_styles %} {% if style['selector'] not in ['position', 'position_float', 'caption', 'toprule', 'midrule', 'bottomrule', 'column_format'] %} diff --git a/pandas/tests/io/formats/style/test_html.py b/pandas/tests/io/formats/style/test_html.py index 6c3abe04db926..74b4c7ea3977c 100644 --- a/pandas/tests/io/formats/style/test_html.py +++ b/pandas/tests/io/formats/style/test_html.py @@ -231,3 +231,8 @@ def test_from_custom_template(tmpdir): assert result.template_html is not Styler.template_html styler = result(DataFrame({"A": [1, 2]})) assert styler.render() + + +def test_caption_as_sequence(styler): + styler.set_caption(("full cap", "short cap")) + assert "" in styler.render() diff --git a/pandas/tests/io/formats/style/test_to_latex.py b/pandas/tests/io/formats/style/test_to_latex.py index 5945502a4c90c..97347bddaa187 100644 --- a/pandas/tests/io/formats/style/test_to_latex.py +++ b/pandas/tests/io/formats/style/test_to_latex.py @@ -438,3 +438,8 @@ def test_parse_latex_table_wrapping(styler): overwrite=False, ) assert _parse_latex_table_wrapping(styler.table_styles, None) is True + + +def test_short_caption(styler): + result = styler.to_latex(caption=("full cap", "short cap")) + assert "\\caption[short cap]{full cap}" in result
{{caption}}{{caption[0]}}full cap