Skip to content

Commit 62c238e

Browse files
authored
BUG: styler render when using hide, MultiIndex and max_rows in combination (#44248)
1 parent 1bd4746 commit 62c238e

File tree

3 files changed

+39
-8
lines changed

3 files changed

+39
-8
lines changed

doc/source/whatsnew/v1.4.0.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ Styler
8181
- Naive sparsification is now possible for LaTeX without the multirow package (:issue:`43369`)
8282
- :meth:`.Styler.to_html` omits CSSStyle rules for hidden table elements (:issue:`43619`)
8383
- Custom CSS classes can now be directly specified without string replacement (:issue:`43686`)
84-
- Bug where row trimming failed to reflect hidden rows (:issue:`43703`)
84+
- Bug where row trimming failed to reflect hidden rows (:issue:`43703`, :issue:`44247`)
8585
- Update and expand the export and use mechanics (:issue:`40675`)
8686
- New method :meth:`.Styler.hide` added and deprecates :meth:`.Styler.hide_index` and :meth:`.Styler.hide_columns` (:issue:`43758`)
8787

pandas/io/formats/style_render.py

+15-7
Original file line numberDiff line numberDiff line change
@@ -1230,29 +1230,37 @@ def _get_level_lengths(
12301230
return lengths
12311231

12321232
for i, lvl in enumerate(levels):
1233+
visible_row_count = 0 # used to break loop due to display trimming
12331234
for j, row in enumerate(lvl):
1234-
if j >= max_index:
1235-
# stop the loop due to display trimming
1235+
if visible_row_count > max_index:
12361236
break
12371237
if not sparsify:
1238+
# then lengths will always equal 1 since no aggregation.
12381239
if j not in hidden_elements:
12391240
lengths[(i, j)] = 1
1241+
visible_row_count += 1
12401242
elif (row is not lib.no_default) and (j not in hidden_elements):
1243+
# this element has not been sparsified so must be the start of section
12411244
last_label = j
12421245
lengths[(i, last_label)] = 1
1246+
visible_row_count += 1
12431247
elif row is not lib.no_default:
1244-
# even if its hidden, keep track of it in case
1245-
# length >1 and later elements are visible
1248+
# even if the above is hidden, keep track of it in case length > 1 and
1249+
# later elements are visible
12461250
last_label = j
12471251
lengths[(i, last_label)] = 0
12481252
elif j not in hidden_elements:
1253+
# then element must be part of sparsified section and is visible
1254+
visible_row_count += 1
12491255
if lengths[(i, last_label)] == 0:
1250-
# if the previous iteration was first-of-kind but hidden then offset
1256+
# if previous iteration was first-of-section but hidden then offset
12511257
last_label = j
12521258
lengths[(i, last_label)] = 1
12531259
else:
1254-
# else add to previous iteration
1255-
lengths[(i, last_label)] += 1
1260+
# else add to previous iteration but do not extend more than max
1261+
lengths[(i, last_label)] = min(
1262+
max_index, 1 + lengths[(i, last_label)]
1263+
)
12561264

12571265
non_zero_lengths = {
12581266
element: length for element, length in lengths.items() if length >= 1

pandas/tests/io/formats/style/test_style.py

+23
Original file line numberDiff line numberDiff line change
@@ -1577,3 +1577,26 @@ def test_row_trimming_hide_index():
15771577
assert len(ctx["body"]) == 3
15781578
for r, val in enumerate(["3", "4", "..."]):
15791579
assert ctx["body"][r][1]["display_value"] == val
1580+
1581+
1582+
def test_row_trimming_hide_index_mi():
1583+
# gh 44247
1584+
df = DataFrame([[1], [2], [3], [4], [5]])
1585+
df.index = MultiIndex.from_product([[0], [0, 1, 2, 3, 4]])
1586+
with pd.option_context("styler.render.max_rows", 2):
1587+
ctx = df.style.hide([(0, 0), (0, 1)], axis="index")._translate(True, True)
1588+
assert len(ctx["body"]) == 3
1589+
1590+
# level 0 index headers (sparsified)
1591+
assert {"value": 0, "attributes": 'rowspan="2"', "is_visible": True}.items() <= ctx[
1592+
"body"
1593+
][0][0].items()
1594+
assert {"value": 0, "attributes": "", "is_visible": False}.items() <= ctx["body"][
1595+
1
1596+
][0].items()
1597+
assert {"value": "...", "is_visible": True}.items() <= ctx["body"][2][0].items()
1598+
1599+
for r, val in enumerate(["2", "3", "..."]):
1600+
assert ctx["body"][r][1]["display_value"] == val # level 1 index headers
1601+
for r, val in enumerate(["3", "4", "..."]):
1602+
assert ctx["body"][r][2]["display_value"] == val # data values

0 commit comments

Comments
 (0)