Skip to content

ENH: Styler.show shorthand alternative to hide #45176

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

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/reference/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v1.4.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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`)
Expand Down
91 changes: 91 additions & 0 deletions pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -2401,6 +2401,10 @@ def hide(
-------
self : Styler

See Also
--------
Styler.show: Show specific rows / columns.

Notes
-----
This method has multiple functionality depending upon the combination
Expand Down Expand Up @@ -2557,6 +2561,93 @@ 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[<subset>, :]` or `DataFrame.loc[:, <subset>]` 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 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
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 to make
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"

visible = []
if head is not None:
visible.extend(getattr(self, obj)[:head])
if tail is not None:
visible.extend(getattr(self, obj)[-tail:])
if subset is not None:
subset_ = IndexSlice[subset, :] if axis == 0 else IndexSlice[:, subset]
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 visible], axis=axis
)

# -----------------------------------------------------------------------
# A collection of "builtin" styles
# -----------------------------------------------------------------------
Expand Down
22 changes: 22 additions & 0 deletions pandas/tests/io/formats/style/test_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -1548,3 +1548,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