Home > Back-end >  How to hide index level in pandas <1.4
How to hide index level in pandas <1.4

Time:06-22

I'm trying to hide an index level from a pandas Styler with pandas 1.3.5. i.e. to replicate the behavior of hide(axis="index", level="level_name") in pandas 1.4.

Here is a minimale example of what I'm trying :

def multi_highlighter(row, range_colors):
    def find_color(value):
        for color, threshold in range_colors.items():
            if value < threshold:
                return color
        return "white"

    return [f"background-color: {find_color(v)}" for v in row]

range_colors = {"red": 18, "orange": 100}

data = pd.DataFrame({
    "Ex Date": ['2022-06-20', '2022-06-20', '2022-06-20', '2022-06-20', '2022-06-20', '2022-06-20', '2022-07-30', '2022-07-30', '2022-07-30'], 
    "Portfolio": ['UUU-SSS', 'UUU-SSS', 'UUU-SSS', 'RRR-DDD', 'RRR-DDD', 'RRR-DDD', 'KKK-VVV', 'KKK-VVV', 'KKK-VVV'],
    "Position": [120, 90, 110, 113, 111, 92, 104, 110, 110],
    "Strike": [18, 18, 19, 19, 20, 20, 15, 18, 19],
    })
(
    data
    .reset_index()
    .set_index(["Ex Date", "Portfolio", "index"])
    .style
    .apply(multi_highlighter, range_colors=range_colors, axis=1)
)

Adding some borders, it produces the following table:

enter image description here

Now to hide the "index" index level, I tried to achieve this by adding CSS styling from this enter image description here

CodePudding user response:

There are a few options in pandas 1.3.5, though this is a non-trivial operation without the use of the hide function available in 1.4.0.

Removing Index Levels >= 1

nth-child is not working here due to the use of rowspans in the MultiIndex. However, we can take advantage of the default CSS classes that are added by the Styler (Styler object using display:none to hide level 2


Removing Index level 0

If trying to remove level0 we only need to hide level0:

hide_column_styles = [
    {
        # Remove all values associated with level0 (including the first header row)
        'selector': f'th.level0:not(.col_heading)',
        'props': [('display', 'none')]
    }
]

The first index column will have the class .level0 and be hidden without needing an additional selector:

<tr>
  <th >&nbsp;</th>
  <th >&nbsp;</th>
  <th >&nbsp;</th> <!-- This will match and be hidden -->
  <th >Position</th>
  <th >Strike</th>
</tr>

Hiding levels that do not affect MultiIndex Uniqueness

If the index levels would remain unique after removing a level it is possible just to Styler object with level 0 dropped before styling

If a level is dropped causing a non-unique MultiIndex (like level 2) a KeyError will occur when using Styler.apply or Styler.applymap:

KeyError: 'Styler.apply and .applymap are not compatible with non-unique index or columns.'


Pandas 1.4.0 and newer

Just to be super clear for any future readers of this question, this is a workaround for versions prior to 1.4.0. It is much simpler to use the Styler object using the hide function with level=2 to hide level 2

  • Related