From e7f4222e8a5972151240cbdc7f8ebe9ce89827f3 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 23 May 2021 18:07:10 +0200 Subject: [PATCH 1/9] add render trimming to Styler --- pandas/core/config_init.py | 10 ++ pandas/io/formats/style_render.py | 156 +++++++++++++++++-- pandas/tests/io/formats/style/test_format.py | 9 ++ pandas/tests/io/formats/style/test_style.py | 8 +- 4 files changed, 170 insertions(+), 13 deletions(-) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index a88bc8900ccdd..27c3c9f8b5d7a 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -743,9 +743,19 @@ def register_converter_cb(key): display each explicit level element in a hierarchical key for each column. """ +styler_max_elements = """ +: int + The maximum number of data-cell () elements that will b rendered before + trimming will occur over columns, rows or both. +""" + with cf.config_prefix("styler"): cf.register_option("sparse.index", True, styler_sparse_index_doc, validator=bool) cf.register_option( "sparse.columns", True, styler_sparse_columns_doc, validator=bool ) + + cf.register_option( + "max.elements", 2 ** 14, styler_sparse_columns_doc, validator=bool + ) diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 9d149008dcb88..710b5a17463a1 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -158,6 +158,8 @@ def _translate(self, sparse_index: bool, sparse_cols: bool): ROW_HEADING_CLASS = "row_heading" COL_HEADING_CLASS = "col_heading" INDEX_NAME_CLASS = "index_name" + TRIMMED_COL_CLASS = "col_trim" + TRIMMED_ROW_CLASS = "row_trim" DATA_CLASS = "data" BLANK_CLASS = "blank" @@ -170,15 +172,34 @@ def _translate(self, sparse_index: bool, sparse_cols: bool): "caption": self.caption, } + max_elements = get_option("styler.max.elements") + max_rows, max_cols = _get_trimming_maximums( + len(self.data.index), len(self.data.columns), max_elements + ) + head = self._translate_header( - BLANK_CLASS, BLANK_VALUE, INDEX_NAME_CLASS, COL_HEADING_CLASS, sparse_cols + BLANK_CLASS, + BLANK_VALUE, + INDEX_NAME_CLASS, + COL_HEADING_CLASS, + sparse_cols, + max_cols, + TRIMMED_COL_CLASS, ) d.update({"head": head}) self.cellstyle_map: DefaultDict[tuple[CSSPair, ...], list[str]] = defaultdict( list ) - body = self._translate_body(DATA_CLASS, ROW_HEADING_CLASS, sparse_index) + body = self._translate_body( + DATA_CLASS, + ROW_HEADING_CLASS, + sparse_index, + max_rows, + max_cols, + TRIMMED_ROW_CLASS, + TRIMMED_COL_CLASS, + ) d.update({"body": body}) cellstyle: list[dict[str, CSSList | list[str]]] = [ @@ -209,6 +230,8 @@ def _translate_header( index_name_class: str, col_heading_class: str, sparsify_cols: bool, + max_cols: int, + trimmed_col_class: str, ): """ Build each within table as a list @@ -234,6 +257,10 @@ def _translate_header( CSS class added to elements within the column_names section of structure. sparsify_cols : bool Whether column_headers section will add colspan attributes (>1) to elements. + max_cols : int + Maximum number of columns to render. If exceeded will contain `...` filler. + trimmed_col_class : str + CSS class added to elements within a column including `...` trimmed vals. Returns ------- @@ -242,10 +269,10 @@ def _translate_header( """ # for sparsifying a MultiIndex col_lengths = _get_level_lengths( - self.columns, sparsify_cols, self.hidden_columns + self.columns, sparsify_cols, max_cols, self.hidden_columns ) - clabels = self.data.columns.tolist() + clabels = self.data.columns.tolist()[:max_cols] # slice to allow trimming if self.data.columns.nlevels == 1: clabels = [[x] for x in clabels] clabels = list(zip(*clabels)) @@ -282,6 +309,18 @@ def _translate_header( ) for c, value in enumerate(clabels[r]) ] + + if len(self.data.columns) > max_cols: + # add an extra column with `...` value to indicate trimming + column_headers.append( + _element( + "th", + f"{col_heading_class} level{r} {trimmed_col_class}", + "...", + True, + attributes="", + ) + ) head.append(index_blanks + column_name + column_headers) # 2) index names @@ -300,6 +339,11 @@ def _translate_header( for c, name in enumerate(self.data.index.names) ] + if len(self.data.columns) <= max_cols: + blank_len = len(clabels[0]) + else: + blank_len = len(clabels[0]) + 1 # to allow room for `...` trim col + column_blanks = [ _element( "th", @@ -307,14 +351,21 @@ def _translate_header( blank_value, c not in self.hidden_columns, ) - for c in range(len(clabels[0])) + for c in range(blank_len) ] head.append(index_names + column_blanks) return head def _translate_body( - self, data_class: str, row_heading_class: str, sparsify_index: bool + self, + data_class: str, + row_heading_class: str, + sparsify_index: bool, + max_rows: int, + max_cols: int, + trimmed_row_class: str, + trimmed_col_class: str, ): """ Build each within table as a list @@ -342,14 +393,52 @@ def _translate_body( The associated HTML elements needed for template rendering. """ # for sparsifying a MultiIndex - idx_lengths = _get_level_lengths(self.index, sparsify_index) + idx_lengths = _get_level_lengths(self.index, sparsify_index, max_rows) - rlabels = self.data.index.tolist() + rlabels = self.data.index.tolist()[:max_rows] # slice to allow trimming if self.data.index.nlevels == 1: rlabels = [[x] for x in rlabels] body = [] for r, row_tup in enumerate(self.data.itertuples()): + if r >= max_rows: # used only to add a '...' trimmed row: + index_headers = [ + _element( + "th", + f"{row_heading_class} level{c} {trimmed_row_class}", + "...", + not self.hidden_index, + attributes="", + ) + for c in range(self.data.index.nlevels) + ] + + data = [ + _element( + "td", + f"{data_class} col{c} {trimmed_row_class}", + "...", + True, + attributes="", + ) + for c in range(max_cols) + ] + + if len(self.data.columns) > max_cols: + # columns are also trimmed so we add the final element + data.append( + _element( + "td", + f"{data_class} {trimmed_row_class} {trimmed_col_class}", + "...", + True, + attributes="", + ) + ) + + body.append(index_headers + data) + break + index_headers = [ _element( "th", @@ -368,6 +457,18 @@ def _translate_body( data = [] for c, value in enumerate(row_tup[1:]): + if c >= max_cols: + data.append( + _element( + "td", + f"{data_class} row{r} {trimmed_col_class}", + "...", + True, + attributes="", + ) + ) + break + # add custom classes from cell context cls = "" if (r, c) in self.cell_context: @@ -584,8 +685,40 @@ def _element( } +def _get_trimming_maximums(rn, cn, max_elements, scaling_factor=0.8): + """ + Recursively reduce the number of rows and columns to satisfy max elements. + + Parameters + ---------- + rn, cn : int + The number of input rows / columns + max_elements : int + The number of allowable elements + + Returns + ------- + rn, cn : tuple + New rn and cn values that satisfy the max_elements constraint + """ + + def scale_down(rn, cn): + if cn >= rn: + return rn, int(cn * scaling_factor) + else: + return int(rn * scaling_factor), cn + + while rn * cn > max_elements: + rn, cn = scale_down(rn, cn) + + return rn, cn + + def _get_level_lengths( - index: Index, sparsify: bool, hidden_elements: Sequence[int] | None = None + index: Index, + sparsify: bool, + max_index: int, + hidden_elements: Sequence[int] | None = None, ): """ Given an index, find the level length for each element. @@ -596,6 +729,8 @@ def _get_level_lengths( Index or columns to determine lengths of each element sparsify : bool Whether to hide or show each distinct element in a MultiIndex + max_index : int + The maximum number of elements to analyse along the index due to trimming hidden_elements : sequence of int Index positions of elements hidden from display in the index affecting length @@ -622,6 +757,9 @@ def _get_level_lengths( for i, lvl in enumerate(levels): for j, row in enumerate(lvl): + if j >= max_index: + # stop the loop due to display trimming + break if not sparsify: lengths[(i, j)] = 1 elif (row is not lib.no_default) and (j not in hidden_elements): diff --git a/pandas/tests/io/formats/style/test_format.py b/pandas/tests/io/formats/style/test_format.py index 9db27689a53f5..1317bb74add37 100644 --- a/pandas/tests/io/formats/style/test_format.py +++ b/pandas/tests/io/formats/style/test_format.py @@ -11,6 +11,7 @@ pytest.importorskip("jinja2") from pandas.io.formats.style import Styler +from pandas.io.formats.style_render import _get_trimming_maximums @pytest.fixture @@ -239,3 +240,11 @@ def test_format_decimal(formatter, thousands, precision): decimal="_", formatter=formatter, thousands=thousands, precision=precision )._translate(True, True) assert "000_123" in result["body"][0][1]["display_value"] + + +def test_trimming_maximum(): + rn, cn = _get_trimming_maximums(100, 100, 100, scaling_factor=0.5) + assert (rn, cn) == (12, 6) + + rn, cn = _get_trimming_maximums(1000, 3, 750, scaling_factor=0.5) + assert (rn, cn) == (250, 3) diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index c556081b5f562..5f60e74b2c5b7 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -940,7 +940,7 @@ def test_get_level_lengths(self): (1, 4): 1, (1, 5): 1, } - result = _get_level_lengths(index, sparsify=True) + result = _get_level_lengths(index, sparsify=True, max_index=100) tm.assert_dict_equal(result, expected) expected = { @@ -957,7 +957,7 @@ def test_get_level_lengths(self): (1, 4): 1, (1, 5): 1, } - result = _get_level_lengths(index, sparsify=False) + result = _get_level_lengths(index, sparsify=False, max_index=100) tm.assert_dict_equal(result, expected) def test_get_level_lengths_un_sorted(self): @@ -971,7 +971,7 @@ def test_get_level_lengths_un_sorted(self): (1, 2): 1, (1, 3): 1, } - result = _get_level_lengths(index, sparsify=True) + result = _get_level_lengths(index, sparsify=True, max_index=100) tm.assert_dict_equal(result, expected) expected = { @@ -984,7 +984,7 @@ def test_get_level_lengths_un_sorted(self): (1, 2): 1, (1, 3): 1, } - result = _get_level_lengths(index, sparsify=False) + result = _get_level_lengths(index, sparsify=False, max_index=100) tm.assert_dict_equal(result, expected) def test_mi_sparse_index_names(self): From 0778a9a9720a53fd88d4155a3243a290582d9a85 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 23 May 2021 20:33:44 +0200 Subject: [PATCH 2/9] render trimming tests --- pandas/tests/io/formats/style/test_style.py | 32 +++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index 5f60e74b2c5b7..1b8ef7d3bdd8c 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -116,6 +116,38 @@ def test_mi_styler_sparsify_options(mi_styler): assert html1 != html2 +def test_render_trimming(): + df = DataFrame(np.arange(120).reshape(60, 2)) + with pd.option_context("styler.max.elements", 6): + ctx = df.style._translate(True, True) + assert len(ctx["head"][0]) == 3 # index + 2 data cols + assert len(ctx["body"]) == 4 # 3 data rows + trimming row + assert len(ctx["body"][0]) == 3 # index + 2 data cols + + df = DataFrame(np.arange(120).reshape(12, 10)) + with pd.option_context("styler.max.elements", 6): + ctx = df.style._translate(True, True) + assert len(ctx["head"][0]) == 4 # index + 2 data cols + trimming row + assert len(ctx["body"]) == 4 # 3 data rows + trimming row + assert len(ctx["body"][0]) == 4 # index + 2 data cols + trimming row + + +def test_render_trimming_mi(): + midx = MultiIndex.from_product([[1, 2], [1, 2, 3]]) + df = DataFrame(np.arange(36).reshape(6, 6), columns=midx, index=midx) + with pd.option_context("styler.max.elements", 4): + ctx = df.style._translate(True, True) + + assert len(ctx["body"][0]) == 5 # 2 indexes + 2 data cols + trimming row + assert {"attributes": 'rowspan="2"'}.items() <= ctx["body"][0][0].items() + assert {"class": "data row0 col_trim"}.items() <= ctx["body"][0][4].items() + assert {"class": "data row_trim col_trim"}.items() <= ctx["body"][2][4].items() + assert len(ctx["body"]) == 3 # 2 data rows + trimming row + + assert len(ctx["head"][0]) == 5 # 2 indexes + 2 column headers + trimming col + assert {"attributes": 'colspan="2"'}.items() <= ctx["head"][0][2].items() + + class TestStyler: def setup_method(self, method): np.random.seed(24) From 1d91f53df20bdf8ee9d1bcab72ff25c4e2f55db7 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 23 May 2021 20:57:42 +0200 Subject: [PATCH 3/9] set default elements --- pandas/core/config_init.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 27c3c9f8b5d7a..79dea4e365f8e 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -757,5 +757,5 @@ def register_converter_cb(key): ) cf.register_option( - "max.elements", 2 ** 14, styler_sparse_columns_doc, validator=bool + "max.elements", 2 ** 18, styler_sparse_columns_doc, validator=bool ) From 0c49d726ab11e82f20c0e4c433062b8cc6404e9d Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 23 May 2021 21:58:06 +0200 Subject: [PATCH 4/9] consistent hidden cols --- pandas/io/formats/style_render.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index 710b5a17463a1..05819cad799c8 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -418,7 +418,7 @@ def _translate_body( "td", f"{data_class} col{c} {trimmed_row_class}", "...", - True, + (c not in self.hidden_columns), attributes="", ) for c in range(max_cols) From 66efb2959253a1e41726daf085cbe0a4adfd8947 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 23 May 2021 22:16:33 +0200 Subject: [PATCH 5/9] docs --- doc/source/user_guide/options.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/source/user_guide/options.rst b/doc/source/user_guide/options.rst index aa8a8fae417be..faaf1bdc310d9 100644 --- a/doc/source/user_guide/options.rst +++ b/doc/source/user_guide/options.rst @@ -487,6 +487,8 @@ styler.sparse.index True "Sparsify" MultiIndex displ elements in outer levels within groups). styler.sparse.columns True "Sparsify" MultiIndex display for columns in Styler output. +styler.max.elements 262144 Maximum number of datapoints that Styler will render + trimming either rows, columns or both to fit. ======================================= ============ ================================== From 99b2d5eee03f4587db2e421654610ba2525b1f75 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Sun, 23 May 2021 22:22:28 +0200 Subject: [PATCH 6/9] whats new --- doc/source/whatsnew/v1.3.0.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index d357e4a633347..aba63f1a9153f 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -138,8 +138,9 @@ The :meth:`.Styler.format` has had upgrades to easily format missing data, precision, and perform HTML escaping (:issue:`40437` :issue:`40134`). There have been numerous other bug fixes to properly format HTML and eliminate some inconsistencies (:issue:`39942` :issue:`40356` :issue:`39807` :issue:`39889` :issue:`39627`) -:class:`.Styler` has also been compatible with non-unique index or columns, at least for as many features as are fully compatible, others made only partially compatible (:issue:`41269`). +:class:`.Styler` has also been made compatible with non-unique index or columns, at least for as many features as are fully compatible, others made only partially compatible (:issue:`41269`). One also has greater control of the display through separate sparsification of the index or columns, using the new 'styler' options context (:issue:`41142`). +Render trimming has also been added for large numbers of data elements to avoid browser overload (:issue:`40712`). Documentation has also seen major revisions in light of new features (:issue:`39720` :issue:`39317` :issue:`40493`) From aed1bbacb3577dd5441c2bc710a6e76a9d9f914d Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Wed, 26 May 2021 08:51:19 +0200 Subject: [PATCH 7/9] merge upstream/master --- pandas/tests/io/formats/style/test_format.py | 9 --------- pandas/tests/io/formats/style/test_style.py | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/pandas/tests/io/formats/style/test_format.py b/pandas/tests/io/formats/style/test_format.py index 1317bb74add37..9db27689a53f5 100644 --- a/pandas/tests/io/formats/style/test_format.py +++ b/pandas/tests/io/formats/style/test_format.py @@ -11,7 +11,6 @@ pytest.importorskip("jinja2") from pandas.io.formats.style import Styler -from pandas.io.formats.style_render import _get_trimming_maximums @pytest.fixture @@ -240,11 +239,3 @@ def test_format_decimal(formatter, thousands, precision): decimal="_", formatter=formatter, thousands=thousands, precision=precision )._translate(True, True) assert "000_123" in result["body"][0][1]["display_value"] - - -def test_trimming_maximum(): - rn, cn = _get_trimming_maximums(100, 100, 100, scaling_factor=0.5) - assert (rn, cn) == (12, 6) - - rn, cn = _get_trimming_maximums(1000, 3, 750, scaling_factor=0.5) - assert (rn, cn) == (250, 3) diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index d82f43cba2e38..ada120941afbe 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -17,6 +17,7 @@ ) from pandas.io.formats.style_render import ( _get_level_lengths, + _get_trimming_maximums, maybe_convert_css_to_tuples, non_reducing_slice, ) @@ -115,6 +116,14 @@ def test_mi_styler_sparsify_options(mi_styler): assert html1 != html2 +def test_trimming_maximum(): + rn, cn = _get_trimming_maximums(100, 100, 100, scaling_factor=0.5) + assert (rn, cn) == (12, 6) + + rn, cn = _get_trimming_maximums(1000, 3, 750, scaling_factor=0.5) + assert (rn, cn) == (250, 3) + + def test_render_trimming(): df = DataFrame(np.arange(120).reshape(60, 2)) with pd.option_context("styler.max.elements", 6): From ada47bf1b65195f01392e0f7347fe049d74ad80e Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Fri, 4 Jun 2021 10:04:06 +0200 Subject: [PATCH 8/9] change option name --- doc/source/user_guide/options.rst | 2 +- doc/source/whatsnew/v1.3.0.rst | 2 +- pandas/core/config_init.py | 6 +++--- pandas/io/formats/style_render.py | 2 +- pandas/tests/io/formats/style/test_style.py | 6 +++--- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/source/user_guide/options.rst b/doc/source/user_guide/options.rst index faaf1bdc310d9..62a347acdaa34 100644 --- a/doc/source/user_guide/options.rst +++ b/doc/source/user_guide/options.rst @@ -487,7 +487,7 @@ styler.sparse.index True "Sparsify" MultiIndex displ elements in outer levels within groups). styler.sparse.columns True "Sparsify" MultiIndex display for columns in Styler output. -styler.max.elements 262144 Maximum number of datapoints that Styler will render +styler.render.max_elements 262144 Maximum number of datapoints that Styler will render trimming either rows, columns or both to fit. ======================================= ============ ================================== diff --git a/doc/source/whatsnew/v1.3.0.rst b/doc/source/whatsnew/v1.3.0.rst index c9a5c14277fe4..6526947a674ce 100644 --- a/doc/source/whatsnew/v1.3.0.rst +++ b/doc/source/whatsnew/v1.3.0.rst @@ -138,7 +138,7 @@ The :meth:`.Styler.format` has had upgrades to easily format missing data, precision, and perform HTML escaping (:issue:`40437` :issue:`40134`). There have been numerous other bug fixes to properly format HTML and eliminate some inconsistencies (:issue:`39942` :issue:`40356` :issue:`39807` :issue:`39889` :issue:`39627`) -:class:`.Styler` has also been made compatible with non-unique index or columns, at least for as many features as are fully compatible, others made only partially compatible (:issue:`41269`). +:class:`.Styler` has also been compatible with non-unique index or columns, at least for as many features as are fully compatible, others made only partially compatible (:issue:`41269`). One also has greater control of the display through separate sparsification of the index or columns, using the new 'styler' options context (:issue:`41142`). Render trimming has also been added for large numbers of data elements to avoid browser overload (:issue:`40712`). diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 79dea4e365f8e..614e7670e5fdb 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -745,8 +745,8 @@ def register_converter_cb(key): styler_max_elements = """ : int - The maximum number of data-cell () elements that will b rendered before - trimming will occur over columns, rows or both. + The maximum number of data-cell () elements that will be rendered before + trimming will occur over columns, rows or both if needed. """ with cf.config_prefix("styler"): @@ -757,5 +757,5 @@ def register_converter_cb(key): ) cf.register_option( - "max.elements", 2 ** 18, styler_sparse_columns_doc, validator=bool + "render.max_elements", 2 ** 18, styler_max_elements, validator=bool ) diff --git a/pandas/io/formats/style_render.py b/pandas/io/formats/style_render.py index a0351e49cce96..7af8802673f80 100644 --- a/pandas/io/formats/style_render.py +++ b/pandas/io/formats/style_render.py @@ -190,7 +190,7 @@ def _translate(self, sparse_index: bool, sparse_cols: bool, blank: str = "  "caption": self.caption, } - max_elements = get_option("styler.max.elements") + max_elements = get_option("styler.render.max_elements") max_rows, max_cols = _get_trimming_maximums( len(self.data.index), len(self.data.columns), max_elements ) diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index ada120941afbe..281170ab6c7cb 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -126,14 +126,14 @@ def test_trimming_maximum(): def test_render_trimming(): df = DataFrame(np.arange(120).reshape(60, 2)) - with pd.option_context("styler.max.elements", 6): + with pd.option_context("styler.render.max_elements", 6): ctx = df.style._translate(True, True) assert len(ctx["head"][0]) == 3 # index + 2 data cols assert len(ctx["body"]) == 4 # 3 data rows + trimming row assert len(ctx["body"][0]) == 3 # index + 2 data cols df = DataFrame(np.arange(120).reshape(12, 10)) - with pd.option_context("styler.max.elements", 6): + with pd.option_context("styler.render.max_elements", 6): ctx = df.style._translate(True, True) assert len(ctx["head"][0]) == 4 # index + 2 data cols + trimming row assert len(ctx["body"]) == 4 # 3 data rows + trimming row @@ -143,7 +143,7 @@ def test_render_trimming(): def test_render_trimming_mi(): midx = MultiIndex.from_product([[1, 2], [1, 2, 3]]) df = DataFrame(np.arange(36).reshape(6, 6), columns=midx, index=midx) - with pd.option_context("styler.max.elements", 4): + with pd.option_context("styler.render.max_elements", 4): ctx = df.style._translate(True, True) assert len(ctx["body"][0]) == 5 # 2 indexes + 2 data cols + trimming row From 59f78194e01261056f78f1617bbbda4c2ee30189 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Fri, 4 Jun 2021 10:07:22 +0200 Subject: [PATCH 9/9] change option name --- pandas/core/config_init.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pandas/core/config_init.py b/pandas/core/config_init.py index 614e7670e5fdb..0db0c5a57207d 100644 --- a/pandas/core/config_init.py +++ b/pandas/core/config_init.py @@ -757,5 +757,8 @@ def register_converter_cb(key): ) cf.register_option( - "render.max_elements", 2 ** 18, styler_max_elements, validator=bool + "render.max_elements", + 2 ** 18, + styler_max_elements, + validator=is_nonnegative_int, )