Skip to content

ENH: styler.latex options #43284

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 10 commits into from
Sep 1, 2021
Merged
4 changes: 4 additions & 0 deletions doc/source/user_guide/options.rst
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,10 @@ styler.format.escape None Whether to escape "html" or
styler.html.mathjax True If set to False will render specific CSS classes to
table attributes that will prevent Mathjax from rendering
in Jupyter Notebook.
styler.latex.multicol_align r Alignment of headers in a merged column due to sparsification. Can be in {"r", "c", "l"}.
styler.latex.multirow_align c Alignment of index labels in a merged row due to sparsification. Can be in {"c", "t", "b"}.
styler.latex.environment None If given will replace the default ``\\begin{table}`` environment. If "longtable" is specified
this will render with a specific "longtable" template with longtable features.
======================================= ============ ==================================


Expand Down
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Styler
- :meth:`.Styler.to_latex` introduces keyword argument ``environment``, which also allows a specific "longtable" entry through a separate jinja2 template (:issue:`41866`).
- :meth:`.Styler.to_html` introduces keyword arguments ``sparse_index``, ``sparse_columns``, ``bold_headers``, ``caption`` (:issue:`41946`, :issue:`43149`).
- Keyword argument ``level`` is added to :meth:`.Styler.hide_index` and :meth:`.Styler.hide_columns` for optionally controlling hidden levels in a MultiIndex (:issue:`25475`)
- Global options have been extended to configure default ``Styler`` properties including formatting and encoding and mathjax options (:issue:`41395`)
- Global options have been extended to configure default ``Styler`` properties including formatting and encoding and mathjax options and LaTeX (:issue:`41395`)

Formerly Styler relied on ``display.html.use_mathjax``, which has now been replaced by ``styler.html.mathjax``.

Expand Down
37 changes: 37 additions & 0 deletions pandas/core/config_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,22 @@ def register_converter_cb(key):
A formatter object to be used as default within ``Styler.format``.
"""

styler_multirow_align = """
: {"c", "t", "b"}
The specifier for vertical alignment of sparsified LaTeX multirows.
"""

styler_multicol_align = """
: {"r", "c", "l"}
The specifier for horizontal alignment of sparsified LaTeX multicolumns.
"""

styler_environment = """
: str
The environment to replace ``\\begin{table}``. If "longtable" is used results
in a specific longtable environment format.
"""

styler_encoding = """
: str
The encoding used for output HTML and LaTeX files.
Expand Down Expand Up @@ -855,3 +871,24 @@ def register_converter_cb(key):
)

cf.register_option("html.mathjax", True, styler_mathjax, validator=is_bool)

cf.register_option(
"latex.multirow_align",
"c",
styler_multirow_align,
validator=is_one_of_factory(["c", "t", "b"]),
)

cf.register_option(
"latex.multicol_align",
"r",
styler_multicol_align,
validator=is_one_of_factory(["r", "c", "l"]),
)

cf.register_option(
"latex.environment",
None,
styler_environment,
validator=is_instance_factory([type(None), str]),
)
21 changes: 13 additions & 8 deletions pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ def to_latex(
caption: str | tuple | None = None,
sparse_index: bool | None = None,
sparse_columns: bool | None = None,
multirow_align: str = "c",
multicol_align: str = "r",
multirow_align: str | None = None,
multicol_align: str | None = None,
siunitx: bool = False,
environment: str | None = None,
encoding: str | None = None,
Expand Down Expand Up @@ -512,18 +512,21 @@ def to_latex(
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.
multirow_align : {"c", "t", "b"}
multirow_align : {"c", "t", "b"}, optional
If sparsifying hierarchical MultiIndexes whether to align text centrally,
at the top or bottom.
multicol_align : {"r", "c", "l"}
at the top or bottom. If not given defaults to
``pandas.options.styler.latex.multirow_align``
multicol_align : {"r", "c", "l"}, optional
If sparsifying hierarchical MultiIndex columns whether to align text at
the left, centrally, or at the right.
the left, centrally, or at the right. If not given defaults to
``pandas.options.styler.latex.multicol_align``
siunitx : bool, default False
Set to ``True`` to structure LaTeX compatible with the {siunitx} package.
environment : str, optional
If given, the environment that will replace 'table' in ``\\begin{table}``.
If 'longtable' is specified then a more suitable template is
rendered.
rendered. If not given defaults to
``pandas.options.styler.latex.environment``.

.. versionadded:: 1.4.0
encoding : str, optional
Expand Down Expand Up @@ -840,7 +843,9 @@ def to_latex(
sparse_index = get_option("styler.sparse.index")
if sparse_columns is None:
sparse_columns = get_option("styler.sparse.columns")

environment = environment or get_option("styler.latex.environment")
multicol_align = multicol_align or get_option("styler.latex.multicol_align")
multirow_align = multirow_align or get_option("styler.latex.multirow_align")
latex = obj._render_latex(
sparse_index=sparse_index,
sparse_columns=sparse_columns,
Expand Down
30 changes: 30 additions & 0 deletions pandas/tests/io/formats/style/test_to_latex.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,30 @@ def test_multiindex_row_and_col(df):
assert s.to_latex(sparse_index=False, sparse_columns=False) == expected


def test_multi_options(df):
cidx = MultiIndex.from_tuples([("Z", "a"), ("Z", "b"), ("Y", "c")])
ridx = MultiIndex.from_tuples([("A", "a"), ("A", "b"), ("B", "c")])
df.loc[2, :] = [2, -2.22, "de"]
df = df.astype({"A": int})
df.index, df.columns = ridx, cidx
styler = df.style.format(precision=2)

expected = dedent(
"""\
{} & {} & \\multicolumn{2}{r}{Z} & {Y} \\\\
{} & {} & {a} & {b} & {c} \\\\
\\multirow[c]{2}{*}{A} & a & 0 & -0.61 & ab \\\\
"""
)
assert expected in styler.to_latex()

with option_context("styler.latex.multicol_align", "l"):
assert "{} & {} & \\multicolumn{2}{l}{Z} & {Y} \\\\" in styler.to_latex()

with option_context("styler.latex.multirow_align", "b"):
assert "\\multirow[b]{2}{*}{A} & a & 0 & -0.61 & ab \\\\" in styler.to_latex()


def test_multiindex_columns_hidden():
df = DataFrame([[1, 2, 3, 4]])
df.columns = MultiIndex.from_tuples([("A", 1), ("A", 2), ("A", 3), ("B", 1)])
Expand Down Expand Up @@ -376,6 +400,12 @@ def test_comprehensive(df, environment):
assert s.format(precision=2).to_latex(environment=environment) == expected


def test_environment_option(styler):
with option_context("styler.latex.environment", "bar-env"):
assert "\\begin{bar-env}" in styler.to_latex()
assert "\\begin{foo-env}" in styler.to_latex(environment="foo-env")


def test_parse_latex_table_styles(styler):
styler.set_table_styles(
[
Expand Down