-
-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
ENH: Enable short_caption in to_latex #35668
Changes from 34 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 | ||||
---|---|---|---|---|---|---|
|
@@ -3002,6 +3002,9 @@ def to_latex( | |||||
.. versionchanged:: 1.0.0 | ||||||
Added caption and label arguments. | ||||||
|
||||||
.. versionchanged:: 1.2.0 | ||||||
Added position argument, changed meaning of caption argument. | ||||||
|
||||||
Parameters | ||||||
---------- | ||||||
buf : str, Path or StringIO-like, optional, default None | ||||||
|
@@ -3063,11 +3066,16 @@ 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 or tuple, optional | ||||||
Tuple (full_caption, short_caption), | ||||||
which results in ``\caption[short_caption]{{full_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 |
||||||
|
||||||
.. versionchanged:: 1.2.0 | ||||||
Optionally allow caption to be a tuple ``(full_caption, short_caption)``. | ||||||
|
||||||
label : str, optional | ||||||
The LaTeX label to be placed inside ``\label{{}}`` in the output. | ||||||
This is used with ``\ref{{}}`` in the main ``.tex`` file. | ||||||
|
@@ -3076,6 +3084,8 @@ def to_latex( | |||||
position : str, optional | ||||||
The LaTeX positional argument for tables, to be placed after | ||||||
``\begin{{}}`` in the output. | ||||||
|
||||||
.. versionadded:: 1.2.0 | ||||||
{returns} | ||||||
See Also | ||||||
-------- | ||||||
|
@@ -3086,8 +3096,8 @@ def to_latex( | |||||
Examples | ||||||
-------- | ||||||
>>> df = pd.DataFrame(dict(name=['Raphael', 'Donatello'], | ||||||
... mask=['red', 'purple'], | ||||||
... weapon=['sai', 'bo staff'])) | ||||||
... mask=['red', 'purple'], | ||||||
... weapon=['sai', 'bo staff'])) | ||||||
>>> print(df.to_latex(index=False)) # doctest: +NORMALIZE_WHITESPACE | ||||||
\begin{{tabular}}{{lll}} | ||||||
\toprule | ||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -2,7 +2,7 @@ | |||||
Module for formatting output data in Latex. | ||||||
""" | ||||||
from abc import ABC, abstractmethod | ||||||
from typing import IO, Iterator, List, Optional, Type | ||||||
from typing import IO, Iterator, List, Optional, Tuple, Type, Union | ||||||
|
||||||
import numpy as np | ||||||
|
||||||
|
@@ -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}}}" | ||||||
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
This can be simplified to get rid of the property 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.
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. @WillAyd, does my answer make sense? 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. @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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. I made string joining (and substitution in place). And removed property |
||||||
return "" | ||||||
|
||||||
@property | ||||||
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. See above - I think can remove this altogether |
||||||
def _short_caption_macro(self) -> str: | ||||||
if self.short_caption: | ||||||
return f"[{self.short_caption}]" | ||||||
return "" | ||||||
|
||||||
@property | ||||||
def _label_macro(self) -> str: | ||||||
|
@@ -596,15 +615,32 @@ def env_end(self) -> str: | |||||
|
||||||
|
||||||
class LatexFormatter(TableFormatter): | ||||||
""" | ||||||
r""" | ||||||
Used to render a DataFrame to a LaTeX tabular/longtable environment output. | ||||||
|
||||||
Parameters | ||||||
---------- | ||||||
formatter : `DataFrameFormatter` | ||||||
longtable : bool, default False | ||||||
Use longtable environment. | ||||||
column_format : str, default None | ||||||
The columns format as specified in `LaTeX table format | ||||||
<https://en.wikibooks.org/wiki/LaTeX/Tables>`__ e.g 'rcl' for 3 columns | ||||||
multicolumn : bool, default False | ||||||
Use \multicolumn to enhance MultiIndex columns. | ||||||
multicolumn_format : str, default 'l' | ||||||
The alignment for multicolumns, similar to `column_format` | ||||||
multirow : bool, default False | ||||||
Use \multirow to enhance MultiIndex rows. | ||||||
caption : str or tuple, optional | ||||||
Tuple (full_caption, short_caption), | ||||||
which results in \caption[short_caption]{full_caption}; | ||||||
if a single string is passed, no short caption will be set. | ||||||
label : str, optional | ||||||
The LaTeX label to be placed inside ``\label{}`` in the output. | ||||||
position : str, optional | ||||||
jreback marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
The LaTeX positional argument for tables, to be placed after | ||||||
``\begin{}`` in the output. | ||||||
|
||||||
See Also | ||||||
-------- | ||||||
|
@@ -619,18 +655,18 @@ def __init__( | |||||
multicolumn: bool = False, | ||||||
multicolumn_format: Optional[str] = None, | ||||||
multirow: bool = False, | ||||||
caption: Optional[str] = None, | ||||||
caption: Optional[Union[str, Tuple[str, str]]] = None, | ||||||
label: Optional[str] = None, | ||||||
position: Optional[str] = None, | ||||||
): | ||||||
self.fmt = formatter | ||||||
self.frame = self.fmt.frame | ||||||
self.longtable = longtable | ||||||
self.column_format = column_format # type: ignore[assignment] | ||||||
self.column_format = column_format | ||||||
self.multicolumn = multicolumn | ||||||
self.multicolumn_format = multicolumn_format | ||||||
self.multirow = multirow | ||||||
self.caption = caption | ||||||
self.caption, self.short_caption = self._split_into_long_short_caption(caption) | ||||||
self.label = label | ||||||
self.position = position | ||||||
|
||||||
|
@@ -658,6 +694,7 @@ def builder(self) -> TableBuilderAbstract: | |||||
multicolumn_format=self.multicolumn_format, | ||||||
multirow=self.multirow, | ||||||
caption=self.caption, | ||||||
short_caption=self.short_caption, | ||||||
label=self.label, | ||||||
position=self.position, | ||||||
) | ||||||
|
@@ -670,8 +707,26 @@ def _select_builder(self) -> Type[TableBuilderAbstract]: | |||||
return RegularTableBuilder | ||||||
return TabularBuilder | ||||||
|
||||||
def _split_into_long_short_caption( | ||||||
self, caption: Optional[Union[str, Tuple[str, str]]] | ||||||
) -> Tuple[str, str]: | ||||||
if caption: | ||||||
if isinstance(caption, str): | ||||||
long_caption = caption | ||||||
short_caption = "" | ||||||
else: | ||||||
try: | ||||||
long_caption, short_caption = caption | ||||||
except ValueError as err: | ||||||
msg = "caption must be either a string or a tuple of two strings" | ||||||
raise ValueError(msg) from err | ||||||
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. Can you add a test that hits this? 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. It is there, if you mean raising ValueError. String 561.
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. I updated the test to ensure that the error message matches expectations. |
||||||
else: | ||||||
long_caption = "" | ||||||
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. can you make this a free function 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. I moved this function to module level. |
||||||
short_caption = "" | ||||||
return long_caption, short_caption | ||||||
|
||||||
@property | ||||||
def column_format(self) -> str: | ||||||
def column_format(self) -> Optional[str]: | ||||||
"""Column format.""" | ||||||
return self._column_format | ||||||
|
||||||
|
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 think we could add a link to to_latest here: https://pandas.pydata.org/docs/user_guide/io.html (followon as prob need a short section as well).