Skip to content

ENH: kw names to Styler.hide_index #43346

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 5 commits into from
Sep 1, 2021
Merged
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
58 changes: 57 additions & 1 deletion pandas/io/formats/style.py
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,8 @@ def _copy(self, deepcopy: bool = False) -> Styler:
shallow = [ # simple string or boolean immutables
"hide_index_",
"hide_columns_",
"hide_column_names",
"hide_index_names",
"table_attributes",
"cell_ids",
"caption",
Expand Down Expand Up @@ -2024,6 +2026,7 @@ def hide_index(
self,
subset: Subset | None = None,
level: Level | list[Level] | None = None,
names: bool = False,
) -> Styler:
"""
Hide the entire index, or specific keys in the index from rendering.
Expand All @@ -2047,6 +2050,11 @@ def hide_index(
The level(s) to hide in a MultiIndex if hiding the entire index. Cannot be
used simultaneously with ``subset``.

.. versionadded:: 1.4.0
names : bool
Whether to hide the index name(s), in the case the index or part of it
remains visible.

.. versionadded:: 1.4.0

Returns
Expand Down Expand Up @@ -2100,7 +2108,7 @@ def hide_index(

Hide a specific level:

>>> df.style.format("{:,.1f").hide_index(level=1) # doctest: +SKIP
>>> df.style.format("{:,.1f}").hide_index(level=1) # doctest: +SKIP
x y
a b c a b c
x 0.1 0.0 0.4 1.3 0.6 -1.4
Expand All @@ -2109,11 +2117,29 @@ def hide_index(
y 0.4 1.0 -0.2 -0.8 -1.2 1.1
-0.6 1.2 1.8 1.9 0.3 0.3
0.8 0.5 -0.3 1.2 2.2 -0.8

Hiding just the index level names:

>>> df.index.names = ["lev0", "lev1"]
>>> df.style.format("{:,.1f}").hide_index(names=True) # doctest: +SKIP
x y
a b c a b c
x a 0.1 0.0 0.4 1.3 0.6 -1.4
b 0.7 1.0 1.3 1.5 -0.0 -0.2
c 1.4 -0.8 1.6 -0.2 -0.4 -0.3
y a 0.4 1.0 -0.2 -0.8 -1.2 1.1
b -0.6 1.2 1.8 1.9 0.3 0.3
c 0.8 0.5 -0.3 1.2 2.2 -0.8
"""
if level is not None and subset is not None:
raise ValueError("`subset` and `level` cannot be passed simultaneously")

if subset is None:
if level is None and names:
# this combination implies user shows the index and hides just names
self.hide_index_names = True
return self

levels_ = _refactor_levels(level, self.index)
self.hide_index_ = [
True if lev in levels_ else False for lev in range(self.index.nlevels)
Expand All @@ -2126,12 +2152,16 @@ def hide_index(
# error: Incompatible types in assignment (expression has type
# "ndarray", variable has type "Sequence[int]")
self.hidden_rows = hrows # type: ignore[assignment]

if names:
self.hide_index_names = True
return self

def hide_columns(
self,
subset: Subset | None = None,
level: Level | list[Level] | None = None,
names: bool = False,
) -> Styler:
"""
Hide the column headers or specific keys in the columns from rendering.
Expand All @@ -2155,6 +2185,11 @@ def hide_columns(
The level(s) to hide in a MultiIndex if hiding the entire column headers
row. Cannot be used simultaneously with ``subset``.

.. versionadded:: 1.4.0
names : bool
Whether to hide the column index name(s), in the case all column headers,
or some levels, are visible.

.. versionadded:: 1.4.0

Returns
Expand Down Expand Up @@ -2221,11 +2256,29 @@ def hide_columns(
y a 0.4 1.0 -0.2 -0.8 -1.2 1.1
b -0.6 1.2 1.8 1.9 0.3 0.3
c 0.8 0.5 -0.3 1.2 2.2 -0.8

Hiding just the column level names:

>>> df.columns.names = ["lev0", "lev1"]
>>> df.style.format("{:.1f").hide_columns(names=True) # doctest: +SKIP
x y
a b c a b c
x a 0.1 0.0 0.4 1.3 0.6 -1.4
b 0.7 1.0 1.3 1.5 -0.0 -0.2
c 1.4 -0.8 1.6 -0.2 -0.4 -0.3
y a 0.4 1.0 -0.2 -0.8 -1.2 1.1
b -0.6 1.2 1.8 1.9 0.3 0.3
c 0.8 0.5 -0.3 1.2 2.2 -0.8
"""
if level is not None and subset is not None:
raise ValueError("`subset` and `level` cannot be passed simultaneously")

if subset is None:
if level is None and names:
# this combination implies user shows the column headers but hides names
self.hide_column_names = True
return self

levels_ = _refactor_levels(level, self.columns)
self.hide_columns_ = [
True if lev in levels_ else False for lev in range(self.columns.nlevels)
Expand All @@ -2238,6 +2291,9 @@ def hide_columns(
# error: Incompatible types in assignment (expression has type
# "ndarray", variable has type "Sequence[int]")
self.hidden_columns = hcols # type: ignore[assignment]

if names:
self.hide_column_names = True
return self

# -----------------------------------------------------------------------
Expand Down
7 changes: 6 additions & 1 deletion pandas/io/formats/style_render.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ def __init__(
self.cell_ids = cell_ids

# add rendering variables
self.hide_index_names: bool = False
self.hide_column_names: bool = False
self.hide_index_: list = [False] * self.index.nlevels
self.hide_columns_: list = [False] * self.columns.nlevels
self.hidden_rows: Sequence[int] = [] # sequence for specific hidden rows/cols
Expand Down Expand Up @@ -334,7 +336,9 @@ def _translate_header(
_element(
"th",
f"{blank_class if name is None else index_name_class} level{r}",
name if name is not None else blank_value,
name
if (name is not None and not self.hide_column_names)
else blank_value,
not all(self.hide_index_),
)
]
Expand Down Expand Up @@ -383,6 +387,7 @@ def _translate_header(
and com.any_not_none(*self.data.index.names)
and not all(self.hide_index_)
and not all(self.hide_columns_)
and not self.hide_index_names
):
index_names = [
_element(
Expand Down
41 changes: 41 additions & 0 deletions pandas/tests/io/formats/style/test_style.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ def mi_styler_comp(mi_styler):
mi_styler.set_table_styles([{"selector": "a", "props": "a:v;"}])
mi_styler.hide_columns()
mi_styler.hide_columns([("c0", "c1_a")])
mi_styler.hide_columns(names=True)
mi_styler.hide_index()
mi_styler.hide_index([("i0", "i1_a")])
mi_styler.hide_index(names=True)
mi_styler.set_table_attributes('class="box"')
mi_styler.format(na_rep="MISSING", precision=3)
mi_styler.highlight_max(axis=None)
Expand Down Expand Up @@ -239,6 +241,8 @@ def test_copy(comprehensive, render, deepcopy, mi_styler, mi_styler_comp):
"cell_ids",
"hide_index_",
"hide_columns_",
"hide_index_names",
"hide_column_names",
"table_attributes",
]
for attr in shallow:
Expand Down Expand Up @@ -1398,3 +1402,40 @@ def test_non_reducing_multi_slice_on_multiindex(self, slice_):
with tm.assert_produces_warning(warn, match=msg):
result = df.loc[non_reducing_slice(slice_)]
tm.assert_frame_equal(result, expected)


def test_hidden_index_names(mi_df):
mi_df.index.names = ["Lev0", "Lev1"]
mi_styler = mi_df.style
ctx = mi_styler._translate(True, True)
assert len(ctx["head"]) == 3 # 2 column index levels + 1 index names row

mi_styler.hide_index(names=True)
ctx = mi_styler._translate(True, True)
assert len(ctx["head"]) == 2 # index names row is unparsed
for i in range(4):
assert ctx["body"][0][i]["is_visible"] # 2 index levels + 2 data values visible

mi_styler.hide_index(level=1)
ctx = mi_styler._translate(True, True)
assert len(ctx["head"]) == 2 # index names row is still hidden
assert ctx["body"][0][0]["is_visible"] is True
assert ctx["body"][0][1]["is_visible"] is False


def test_hidden_column_names(mi_df):
mi_df.columns.names = ["Lev0", "Lev1"]
mi_styler = mi_df.style
ctx = mi_styler._translate(True, True)
assert ctx["head"][0][1]["display_value"] == "Lev0"
assert ctx["head"][1][1]["display_value"] == "Lev1"

mi_styler.hide_columns(names=True)
ctx = mi_styler._translate(True, True)
assert ctx["head"][0][1]["display_value"] == " "
assert ctx["head"][1][1]["display_value"] == " "

mi_styler.hide_columns(level=0)
ctx = mi_styler._translate(True, True)
assert len(ctx["head"]) == 1 # no index names and only one visible column headers
assert ctx["head"][0][1]["display_value"] == " "