Skip to content

Commit a22bdc5

Browse files
authored
BUG: styler.concat should raise when index nlevels are incompatible (#46180)
1 parent 7001e9a commit a22bdc5

File tree

3 files changed

+30
-3
lines changed

3 files changed

+30
-3
lines changed

pandas/io/formats/style.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,8 @@ def concat(self, other: Styler) -> Styler:
281281
----------
282282
other : Styler
283283
The other Styler object which has already been styled and formatted. The
284-
data for this Styler must have the same columns as the original.
284+
data for this Styler must have the same columns as the original, and the
285+
number of index levels must also be the same to render correctly.
285286
286287
Returns
287288
-------
@@ -344,11 +345,24 @@ def concat(self, other: Styler) -> Styler:
344345
>>> styler.concat(other) # doctest: +SKIP
345346
346347
.. figure:: ../../_static/style/footer_extended.png
348+
349+
When ``other`` has fewer index levels than the original Styler it is possible
350+
to extend the index in ``other``, with placeholder levels.
351+
352+
>>> df = DataFrame([[1], [2]], index=pd.MultiIndex.from_product([[0], [1, 2]]))
353+
>>> descriptors = df.agg(["sum"])
354+
>>> descriptors.index = pd.MultiIndex.from_product([[""], descriptors.index])
355+
>>> df.style.concat(descriptors.style) # doctest: +SKIP
347356
"""
348357
if not isinstance(other, Styler):
349358
raise TypeError("`other` must be of type `Styler`")
350359
if not self.data.columns.equals(other.data.columns):
351360
raise ValueError("`other.data` must have same columns as `Styler.data`")
361+
if not self.data.index.nlevels == other.data.index.nlevels:
362+
raise ValueError(
363+
"number of index levels must be same in `other` "
364+
"as in `Styler`. See documentation for suggestions."
365+
)
352366
self.concatenated = other
353367
return self
354368

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22

33
jinja2 = pytest.importorskip("jinja2")
44

5-
from pandas import DataFrame
5+
from pandas import (
6+
DataFrame,
7+
MultiIndex,
8+
)
69

710
from pandas.io.formats.style import Styler
811

@@ -31,3 +34,11 @@ def test_concat_bad_type(styler):
3134
msg = "`other` must be of type `Styler`"
3235
with pytest.raises(TypeError, match=msg):
3336
styler.concat(DataFrame([[1, 2]]))
37+
38+
39+
def test_concat_bad_index_levels(styler, df):
40+
df = df.copy()
41+
df.index = MultiIndex.from_tuples([(0, 0), (1, 1)])
42+
msg = "number of index levels must be same in `other`"
43+
with pytest.raises(ValueError, match=msg):
44+
styler.concat(df.style)

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ def mi_styler_comp(mi_styler):
5656
mi_styler.hide(axis="index")
5757
mi_styler.hide([("i0", "i1_a")], axis="index", names=True)
5858
mi_styler.set_table_attributes('class="box"')
59-
mi_styler.concat(mi_styler.data.agg(["mean"]).style)
59+
other = mi_styler.data.agg(["mean"])
60+
other.index = MultiIndex.from_product([[""], other.index])
61+
mi_styler.concat(other.style)
6062
mi_styler.format(na_rep="MISSING", precision=3)
6163
mi_styler.format_index(precision=2, axis=0)
6264
mi_styler.format_index(precision=4, axis=1)

0 commit comments

Comments
 (0)