Skip to content

ENH: add long and short captions to Styler.to_latex #41659

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Jun 4, 2021
19 changes: 11 additions & 8 deletions pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would emphasize here and below tht this is (full caption, short caption)

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 ``<table>`` tag
in addition to automatic (by default) id.
Expand Down Expand Up @@ -172,7 +172,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,
Expand Down Expand Up @@ -416,7 +416,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",
Expand Down Expand Up @@ -457,8 +457,9 @@ def to_latex(
label : str, optional
The LaTeX label included as: \\label{<label>}.
This is used with \\ref{<label>} in the main .tex file.
caption : str, optional
The LaTeX table caption included as: \\caption{<caption>}.
caption : str, tuple, optional
If string, the LaTeX table caption included as: \\caption{<caption>}.
If tuple, the caption included as: \\caption[<caption[0]>]{<caption[1]>}.
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.
Expand Down Expand Up @@ -1273,13 +1274,15 @@ 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 ``<caption>`` HTML element.

Parameters
----------
caption : str
caption : str, tuple
For HTML output only string input is used, for LaTeX the additional
tuple input allows for short and long captions.

Returns
-------
Expand Down
2 changes: 1 addition & 1 deletion pandas/io/formats/style_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
):

Expand Down
2 changes: 1 addition & 1 deletion pandas/io/formats/templates/html.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
{% block table %}
<table id="T_{{uuid}}"{% if table_attributes %} {{table_attributes}}{% endif %}>
{% block caption %}
{% if caption %}
{% if caption and caption is string %}
<caption>{{caption}}</caption>
{% endif %}
{% endblock caption %}
Expand Down
5 changes: 4 additions & 1 deletion pandas/io/formats/templates/latex.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -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[0]}}]{% raw %}{{% endraw %}{{caption[1]}}{% raw %}}{% endraw %}

{% endif %}
{% for style in table_styles %}
{% if style['selector'] not in ['position', 'position_float', 'caption', 'toprule', 'midrule', 'bottomrule', 'column_format'] %}
Expand Down
5 changes: 5 additions & 0 deletions pandas/tests/io/formats/style/test_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -1502,3 +1502,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_no_sequence(mi_styler):
mi_styler.set_caption(("short cap", "long_cap"))
assert "<caption>" not in mi_styler.render()
5 changes: 5 additions & 0 deletions pandas/tests/io/formats/style/test_to_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -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_long_captions(styler):
result = styler.to_latex(caption=("short cap", "long cap"))
assert "\\caption[short cap]{long cap}" in result
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you replicate the existing behavior as here https://github.com/pandas-dev/pandas/pull/35668/files?
Currently in DataFrame.to_latex we can pass a string full_caption or a tuple (full_caption, short_caption).
In your code it is vice versa (short_caption, full_caption).
Also I would rename this test function to test_short_caption, since it targets a feature of adding a short caption.
In addition, you would need to change the indices in the docstring as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. easy fix. should be ok now.