-
-
Notifications
You must be signed in to change notification settings - Fork 19.1k
ENH: Enable short_caption in to_latex #35668
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
Changes from 12 commits
13d07ae
8912c81
3f71b46
22d2ca4
01152c1
6adb05c
4725d73
a7b64c0
a2216a1
6c93de4
45de6eb
e70aafa
a0e3f53
6725ca8
8466421
0cc0664
c60a705
27891a3
e43b52f
fbea9eb
29b37e2
ed0132c
ed4b705
3453d43
16884bc
6fd52ca
5acfc44
ae1babe
ddec116
15227b3
336bfb5
b30d2d7
f1781f6
f4b18ff
a18c85d
e957c37
09d9c85
559ca2a
0fd73e8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -3074,11 +3074,12 @@ def to_latex( | |||||
centered labels (instead of top-aligned) across the contained | ||||||
rows, separating groups via clines. The default will be read | ||||||
from the pandas config module. | ||||||
caption : str, optional | ||||||
The LaTeX caption to be placed inside ``\caption{}`` in the output. | ||||||
caption : str, tuple, optional | ||||||
Tuple (short_caption, full_caption), | ||||||
which results in \caption[short_caption]{caption}; | ||||||
if a single string is passed, no short caption will be set. | ||||||
|
||||||
.. versionadded:: 1.0.0 | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But I think I should keep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure. can have both. and add a one-liner describing the changes. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added these tags for caption, position (PR #35284) and |
||||||
|
||||||
label : str, optional | ||||||
The LaTeX label to be placed inside ``\label{}`` in the output. | ||||||
This is used with ``\ref{}`` in the main ``.tex`` file. | ||||||
|
@@ -3123,6 +3124,18 @@ def to_latex( | |||||
if multirow is None: | ||||||
multirow = config.get_option("display.latex.multirow") | ||||||
|
||||||
if caption: | ||||||
|
||||||
if isinstance(caption, str): | ||||||
short_caption = "" | ||||||
else: | ||||||
try: | ||||||
caption, short_caption = caption | ||||||
except ValueError as err: | ||||||
msg = "caption must be either str or tuple of two strings" | ||||||
raise ValueError(msg) from err | ||||||
else: | ||||||
short_caption = None | ||||||
|
||||||
formatter = DataFrameFormatter( | ||||||
self, | ||||||
columns=columns, | ||||||
|
@@ -3147,6 +3160,7 @@ def to_latex( | |||||
multicolumn_format=multicolumn_format, | ||||||
multirow=multirow, | ||||||
caption=caption, | ||||||
short_caption=short_caption, | ||||||
label=label, | ||||||
position=position, | ||||||
) | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -931,6 +931,7 @@ def to_latex( | |
multicolumn_format: Optional[str] = None, | ||
multirow: bool = False, | ||
caption: Optional[str] = None, | ||
short_caption: Optional[str] = None, | ||
|
||
label: Optional[str] = None, | ||
position: Optional[str] = None, | ||
) -> Optional[str]: | ||
|
@@ -947,6 +948,7 @@ def to_latex( | |
multicolumn_format=multicolumn_format, | ||
multirow=multirow, | ||
caption=caption, | ||
short_caption=short_caption, | ||
label=label, | ||
position=position, | ||
) | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -275,6 +275,8 @@ class TableBuilderAbstract(ABC): | |||||
Use multirow to enhance MultiIndex rows. | ||||||
caption: str, optional | ||||||
Table caption. | ||||||
short_caption: str, optional | ||||||
Table short caption. | ||||||
label: str, optional | ||||||
LaTeX label. | ||||||
position: str, optional | ||||||
|
@@ -289,6 +291,7 @@ def __init__( | |||||
multicolumn_format: Optional[str] = None, | ||||||
multirow: bool = False, | ||||||
caption: Optional[str] = None, | ||||||
short_caption: Optional[str] = None, | ||||||
label: Optional[str] = None, | ||||||
position: Optional[str] = None, | ||||||
): | ||||||
|
@@ -298,6 +301,7 @@ def __init__( | |||||
self.multicolumn_format = multicolumn_format | ||||||
self.multirow = multirow | ||||||
self.caption = caption | ||||||
self.short_caption = short_caption | ||||||
self.label = label | ||||||
self.position = position | ||||||
|
||||||
|
@@ -384,8 +388,23 @@ def _position_macro(self) -> str: | |||||
|
||||||
@property | ||||||
def _caption_macro(self) -> str: | ||||||
r"""Caption macro, extracted from self.caption, like \caption{cap}.""" | ||||||
return f"\\caption{{{self.caption}}}" if self.caption else "" | ||||||
r"""Caption macro, extracted from self.caption. | ||||||
|
||||||
With short caption: | ||||||
\caption[short_caption]{caption_string}. | ||||||
|
||||||
Without short caption: | ||||||
\caption{caption_string}. | ||||||
""" | ||||||
if self.caption: | ||||||
return f"\\caption{self._short_caption_macro}{{{self.caption}}}" | ||||||
|
return f"\\caption{self._short_caption_macro}{{{self.caption}}}" | |
return f"\\caption{self._short_caption or ''}{{{self.caption}}}" |
This can be simplified to get rid of the property
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
short_caption_macro
is either an empty string or [short caption text]
(in square brackets).
Putting this logic into f-string seems to be rather complicated.
IMHO having a separate property (_short_caption_macro
) with clear intent is more readable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@WillAyd, does my answer make sense?
@jreback, @simonjayhawkins, @toobaz, any plans on merging this?
Or does it require additional work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ivanovmg am looking now, we have 200 open PRs; these take time
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the way you have it is ok; the f-string actually is pretty complicated to grok on the substitutions. if you can make it simpler would take (e.g. use concatenation maybe)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made string joining (and substitution in place). And removed property _short_caption_macro
as @WillAyd suggested. Would you consider it more readable?
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above - I think can remove this altogether
jreback marked this conversation as resolved.
Show resolved
Hide resolved
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -459,6 +459,7 @@ def test_to_latex_longtable(self): | |
def test_to_latex_caption_label(self): | ||
# GH 25436 | ||
the_caption = "a table in a \\texttt{table/tabular} environment" | ||
the_short_caption = "a table" | ||
the_label = "tab:table_tabular" | ||
|
||
df = DataFrame({"a": [1, 2], "b": ["b1", "b2"]}) | ||
|
@@ -515,12 +516,73 @@ def test_to_latex_caption_label(self): | |
\bottomrule | ||
\end{tabular} | ||
\end{table} | ||
""" | ||
assert result_cl == expected_cl | ||
|
||
# test when the short_caption is provided alongside caption | ||
|
||
result_cl = df.to_latex(caption=(the_caption, the_short_caption)) | ||
|
||
expected_cl = r"""\begin{table} | ||
\centering | ||
\caption[a table]{a table in a \texttt{table/tabular} environment} | ||
\begin{tabular}{lrl} | ||
\toprule | ||
{} & a & b \\ | ||
\midrule | ||
0 & 1 & b1 \\ | ||
1 & 2 & b2 \\ | ||
\bottomrule | ||
\end{tabular} | ||
\end{table} | ||
""" | ||
assert result_cl == expected_cl | ||
|
||
# test when the short_caption is provided alongside caption and label | ||
result_cl = df.to_latex( | ||
caption=(the_caption, the_short_caption), label=the_label, | ||
) | ||
|
||
expected_cl = r"""\begin{table} | ||
\centering | ||
\caption[a table]{a table in a \texttt{table/tabular} environment} | ||
\label{tab:table_tabular} | ||
\begin{tabular}{lrl} | ||
\toprule | ||
{} & a & b \\ | ||
\midrule | ||
0 & 1 & b1 \\ | ||
1 & 2 & b2 \\ | ||
\bottomrule | ||
\end{tabular} | ||
\end{table} | ||
""" | ||
assert result_cl == expected_cl | ||
|
||
# test that wrong number of params is raised | ||
with pytest.raises(ValueError): | ||
df.to_latex(caption=(the_caption, the_short_caption, "extra_string")) | ||
|
||
# test that two chars caption is handled correctly | ||
result_cl = df.to_latex(caption="xy") | ||
expected_cl = r"""\begin{table} | ||
\centering | ||
\caption{xy} | ||
\begin{tabular}{lrl} | ||
\toprule | ||
{} & a & b \\ | ||
\midrule | ||
0 & 1 & b1 \\ | ||
1 & 2 & b2 \\ | ||
\bottomrule | ||
\end{tabular} | ||
\end{table} | ||
""" | ||
assert result_cl == expected_cl | ||
|
||
def test_to_latex_longtable_caption_label(self): | ||
# GH 25436 | ||
the_caption = "a table in a \\texttt{longtable} environment" | ||
the_short_caption = "a table" | ||
the_label = "tab:longtable" | ||
|
||
df = DataFrame({"a": [1, 2], "b": ["b1", "b2"]}) | ||
|
@@ -584,6 +646,31 @@ def test_to_latex_longtable_caption_label(self): | |
\midrule | ||
\endfoot | ||
|
||
\bottomrule | ||
\endlastfoot | ||
0 & 1 & b1 \\ | ||
1 & 2 & b2 \\ | ||
\end{longtable} | ||
""" | ||
assert result_cl == expected_cl | ||
|
||
# test when the caption, the short_caption and the label are provided | ||
|
||
result_cl = df.to_latex( | ||
longtable=True, caption=(the_caption, the_short_caption), label=the_label, | ||
) | ||
|
||
expected_cl = r"""\begin{longtable}{lrl} | ||
\caption[a table]{a table in a \texttt{longtable} environment} | ||
\label{tab:longtable}\\ | ||
\toprule | ||
{} & a & b \\ | ||
\midrule | ||
\endhead | ||
\midrule | ||
\multicolumn{3}{r}{{Continued on next page}} \\ | ||
\midrule | ||
\endfoot | ||
|
||
\bottomrule | ||
\endlastfoot | ||
0 & 1 & b1 \\ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
str or tuple, optional (change the signature as well)
Optional[Union[str, Tuple[str, str]]]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I updated typing on caption in DataFrameFormatter.to_latex() and LatexFormatter.