From 97efadf90b5e112c7e3de3fd5ff43ead528a9ce0 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 29 Aug 2021 12:19:23 +0200 Subject: [PATCH 1/6] add options config --- pandas/core/config_init.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 27b898782fbef..7b4c1c5ca29d1 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -762,6 +762,22 @@ def register_converter_cb(key): trimming will occur over columns, rows or both if needed. """ +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. +""" + with cf.config_prefix("styler"): cf.register_option("sparse.index", True, styler_sparse_index_doc, validator=bool) @@ -775,3 +791,24 @@ def register_converter_cb(key): styler_max_elements, validator=is_nonnegative_int, ) + + 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]), + ) From d728621041f4d2c6eaae1621591c9f8013db6c4b Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 29 Aug 2021 12:23:31 +0200 Subject: [PATCH 2/6] options .rst --- doc/source/user_guide/options.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/source/user_guide/options.rst b/doc/source/user_guide/options.rst index 62a347acdaa34..51743d8b3dcc9 100644 --- a/doc/source/user_guide/options.rst +++ b/doc/source/user_guide/options.rst @@ -489,6 +489,10 @@ styler.sparse.columns True "Sparsify" MultiIndex displ in Styler output. styler.render.max_elements 262144 Maximum number of datapoints that Styler will render trimming either rows, columns or both to fit. +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. ======================================= ============ ================================== From 13c38ea7bcf738056ae5902432da03d3de50f994 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 29 Aug 2021 12:31:50 +0200 Subject: [PATCH 3/6] method edit and docstrings --- pandas/io/formats/style.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 5d523f59a46f8..07b91cdb986ce 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -437,8 +437,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, @@ -491,18 +491,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, default "utf-8" @@ -818,7 +821,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, From 6ea1fb676a7de851adc77afce032c905ca73473e Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 29 Aug 2021 12:43:41 +0200 Subject: [PATCH 4/6] add options tests --- .../tests/io/formats/style/test_to_latex.py | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/pandas/tests/io/formats/style/test_to_latex.py b/pandas/tests/io/formats/style/test_to_latex.py index ac164f2de9fb2..046c7be1b18fb 100644 --- a/pandas/tests/io/formats/style/test_to_latex.py +++ b/pandas/tests/io/formats/style/test_to_latex.py @@ -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)]) From 5c042a529e323eb9825a87618b141e8f5a226124 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 29 Aug 2021 12:47:05 +0200 Subject: [PATCH 5/6] add options tests --- pandas/tests/io/formats/style/test_to_latex.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/pandas/tests/io/formats/style/test_to_latex.py b/pandas/tests/io/formats/style/test_to_latex.py index 046c7be1b18fb..914eeff97c0fe 100644 --- a/pandas/tests/io/formats/style/test_to_latex.py +++ b/pandas/tests/io/formats/style/test_to_latex.py @@ -400,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( [ From 0078e7757442e7dab17219e15990bc2b8a323f87 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 29 Aug 2021 12:51:27 +0200 Subject: [PATCH 6/6] whats new --- doc/source/whatsnew/v1.4.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 450ecc85c725b..3c1b758d8d8e2 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -75,6 +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`` and ``sparse_columns`` (:issue:`41946`) - 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 latex options (:issue:`41395`) There are also bug fixes and deprecations listed below.