From 6ac56608e4e0376918d0e6019aee83bd83a775d6 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Sat, 1 Jan 2022 20:19:54 +0100 Subject: [PATCH 1/5] setup docs --- pandas/io/formats/style.py | 76 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index acfa8e955a335..265713270af5d 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -2383,6 +2383,10 @@ def hide( ------- self : Styler + See Also + -------- + Styler.show: Show specific rows / columns. + Notes ----- This method has multiple functionality depending upon the combination @@ -2539,6 +2543,78 @@ def hide( setattr(self, f"hide_{obj}_names", True) return self + def show( + self, + subset: Subset | None = None, + axis: Axis = 0, + head: int | None = None, + tail: int | None = None, + ) -> Styler: + """ + Show specific rows / columns in the display. + + .. versionadded:: 1.4.0 + + Parameters + ---------- + subset : label, array-like, IndexSlice, optional + A valid 1d input or single key along the axis within + `DataFrame.loc[, :]` or `DataFrame.loc[:, ]` depending + upon ``axis``, to limit ``data`` to select specific rows / columns. + axis : {"index", 0, "columns", 1} + Apply to the index or columns. + head : int, optional + The number of rows / columns at the start of the axis-index to show. + tail : int, optional + The number of rows / columns at the end of the axis-index to show. + + Returns + ------- + self : Styler + + See Also + -------- + Styler.hide: Hide the entire index / columns, or specific rows / columns. + + Notes + ----- + This is a wrapper of :meth:`Styler.hide`, where the inputs are internally + restructured to a call to `Styler.hide`. It is recommended to use `Styler.show` + exclusively, and with only one call per axis, as a form of convenient + data exploration. For more specific control of removing items from the + display it is recommended to use `Styler.hide`, with as many successive calls + as is required. + + The technical explanation for this recommendation is that at instantiation + `Styler` is configured to display all datapoints and all aspects of the + index and column headers of a DataFrame, + but `Styler.hide` can be called to selectively, and successively, remove + items from that default display. + + For example, given an index of `[0, 1, 2, 3]`, calling: + + .. code-block:: python + + styler.hide([0, 1]).hide([2, 3]) + + will first hide the first 2 index labels and then, subsequently, also hide the + final 2 labels, resulting in hiding all of the rows and displaying none. + + In this case `styler.show([0, 1])` is refactored as the call + `styler.hide([v for v in styler.index if v not in [0, 1]])` which is + equivalently `styler.hide([2, 3])` so performing: + + .. code-block:: python + + styler.hide([0, 1]).show([0, 1]) + + is effectively the same as the above and will also result in all rows hidden. + + `Styler.hide` will always only add items to the set that is considered hidden. + It never removes items, that have been previously added, from that set. + """ + pass + # ----------------------------------------------------------------------- # A collection of "builtin" styles # ----------------------------------------------------------------------- From a731c341dda1ddc44ea9bb62c12dc4f2438d14cf Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Mon, 3 Jan 2022 10:39:27 +0100 Subject: [PATCH 2/5] add method and tests --- pandas/io/formats/style.py | 19 ++++++++++++++++-- pandas/tests/io/formats/style/test_style.py | 22 +++++++++++++++++++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 040ac7aacf9b5..adaeb625bd5a8 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -2611,9 +2611,24 @@ def show( is effectively the same as the above and will also result in all rows hidden. `Styler.hide` will always only add items to the set that is considered hidden. - It never removes items, that have been previously added, from that set. + It never removes items, that have been previously added, from that set to make + them visible again. """ - pass + axis = self.data._get_axis_number(axis) + obj = "index" if axis == 0 else "columns" + + unhidden = [] + if head is not None: + unhidden.extend(getattr(self, obj)[:head]) + if tail is not None: + unhidden.extend(getattr(self, obj)[-tail:]) + if subset is not None: + subset_ = IndexSlice[subset, :] if axis == 0 else IndexSlice[:, subset] + unhidden.extend(getattr(self.data.loc[non_reducing_slice(subset_)], obj)) + + return self.hide( + subset=[v for v in getattr(self, obj) if v not in unhidden], axis=axis + ) # ----------------------------------------------------------------------- # A collection of "builtin" styles diff --git a/pandas/tests/io/formats/style/test_style.py b/pandas/tests/io/formats/style/test_style.py index fa054ff7ca6c0..04695f8c16e18 100644 --- a/pandas/tests/io/formats/style/test_style.py +++ b/pandas/tests/io/formats/style/test_style.py @@ -1547,3 +1547,25 @@ def test_col_trimming_hide_columns(): assert ctx["head"][0][c + 2]["is_visible"] == vals[1] assert len(ctx["body"][0]) == 6 # index + 2 hidden + 2 visible + trimming col + + +@pytest.mark.parametrize( + "kwargs, exp", + [ + ({"head": 2}, [3, 4]), + ({"tail": 2}, [1, 2]), + ({"subset": [2, 3]}, [1, 4]), + ({"head": 1, "tail": 1}, [2, 3]), + ({"head": 2, "subset": [2, 3]}, [4]), + ({"tail": 2, "subset": [2, 3]}, [1]), + ({"tail": 1, "subset": [2, 3], "head": 1}, []), + ], +) +@pytest.mark.parametrize("axis", ["index", "columns"]) +def test_show(kwargs, exp, axis): + df = DataFrame(np.random.randn(4, 4), index=[1, 2, 3, 4], columns=[1, 2, 3, 4]) + styler = Styler(df, uuid_len=0) + result = styler.show(axis=axis, **kwargs)._translate(True, True) + styler2 = Styler(df, uuid_len=0) + expected = styler2.hide(subset=exp, axis=axis)._translate(True, True) + assert result == expected From cb11e20754f23ea39c22e59b16baa8f1cd0fa39b Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Mon, 3 Jan 2022 13:58:23 +0100 Subject: [PATCH 3/5] whats new --- doc/source/whatsnew/v1.4.0.rst | 1 + pandas/io/formats/style.py | 14 +++++++------- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/doc/source/whatsnew/v1.4.0.rst b/doc/source/whatsnew/v1.4.0.rst index 4c3e53ddcfa26..74fda9b43130b 100644 --- a/doc/source/whatsnew/v1.4.0.rst +++ b/doc/source/whatsnew/v1.4.0.rst @@ -87,6 +87,7 @@ Styler - Styling and formatting of indexes has been added, with :meth:`.Styler.apply_index`, :meth:`.Styler.applymap_index` and :meth:`.Styler.format_index`. These mirror the signature of the methods already used to style and format data values, and work with both HTML, LaTeX and Excel format (:issue:`41893`, :issue:`43101`, :issue:`41993`, :issue:`41995`) - The new method :meth:`.Styler.hide` deprecates :meth:`.Styler.hide_index` and :meth:`.Styler.hide_columns` (:issue:`43758`) + - The new method :meth:`.Styler.show` provides a convenient refactorisation of :meth:`.Styler.hide` for specific rows and column labels, including ``head`` and ``tail`` options (:issue:`?????`) - The keyword arguments ``level`` and ``names`` have been added to :meth:`.Styler.hide` (and implicitly to the deprecated methods :meth:`.Styler.hide_index` and :meth:`.Styler.hide_columns`) for additional control of visibility of MultiIndexes and of index names (:issue:`25475`, :issue:`43404`, :issue:`43346`) - The :meth:`.Styler.export` and :meth:`.Styler.use` have been updated to address all of the added functionality from v1.2.0 and v1.3.0 (:issue:`40675`) - Global options under the category ``pd.options.styler`` have been extended to configure default ``Styler`` properties which address formatting, encoding, and HTML and LaTeX rendering. Note that formerly ``Styler`` relied on ``display.html.use_mathjax``, which has now been replaced by ``styler.html.mathjax``. (:issue:`41395`) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index adaeb625bd5a8..d16625b6df0e4 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -2578,12 +2578,12 @@ def show( Notes ----- - This is a wrapper of :meth:`Styler.hide`, where the inputs are internally - restructured to a call to `Styler.hide`. It is recommended to use `Styler.show` - exclusively, and with only one call per axis, as a form of convenient - data exploration. For more specific control of removing items from the - display it is recommended to use `Styler.hide`, with as many successive calls - as is required. + This is a simplified wrapper of :meth:`Styler.hide`, where the inputs are + internally restructured to a call to `Styler.hide`. It is recommended to + use `Styler.show` exclusively, and with only one call per axis, as a form of + convenient data exploration. For more specific control of removing items from + the display it is recommended to use `Styler.hide`, with as many successive + calls as is required. The technical explanation for this recommendation is that at instantiation `Styler` is configured to display all datapoints and all aspects of the @@ -2612,7 +2612,7 @@ def show( `Styler.hide` will always only add items to the set that is considered hidden. It never removes items, that have been previously added, from that set to make - them visible again. + them visible again. This is done to provide consistent method chaining. """ axis = self.data._get_axis_number(axis) obj = "index" if axis == 0 else "columns" From a67a33e5be4395d1a2b603d5ca4cb85fa73c5fe5 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Mon, 3 Jan 2022 14:08:09 +0100 Subject: [PATCH 4/5] doc link --- doc/source/reference/style.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/reference/style.rst b/doc/source/reference/style.rst index a739993e4d376..8ba0aa8282608 100644 --- a/doc/source/reference/style.rst +++ b/doc/source/reference/style.rst @@ -41,6 +41,7 @@ Style application Styler.format Styler.format_index Styler.hide + Styler.show Styler.set_td_classes Styler.set_table_styles Styler.set_table_attributes From ba02dfdaee3131e4cd3ed549b68f67ae946dc603 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (MBP)" Date: Mon, 3 Jan 2022 18:16:11 +0100 Subject: [PATCH 5/5] better var name --- pandas/io/formats/style.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index d16625b6df0e4..389f6b2432de1 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -2617,17 +2617,17 @@ def show( axis = self.data._get_axis_number(axis) obj = "index" if axis == 0 else "columns" - unhidden = [] + visible = [] if head is not None: - unhidden.extend(getattr(self, obj)[:head]) + visible.extend(getattr(self, obj)[:head]) if tail is not None: - unhidden.extend(getattr(self, obj)[-tail:]) + visible.extend(getattr(self, obj)[-tail:]) if subset is not None: subset_ = IndexSlice[subset, :] if axis == 0 else IndexSlice[:, subset] - unhidden.extend(getattr(self.data.loc[non_reducing_slice(subset_)], obj)) + visible.extend(getattr(self.data.loc[non_reducing_slice(subset_)], obj)) return self.hide( - subset=[v for v in getattr(self, obj) if v not in unhidden], axis=axis + subset=[v for v in getattr(self, obj) if v not in visible], axis=axis ) # -----------------------------------------------------------------------