St.dataframe style column with multi-index column

I am trying to apply column styling to a dataframe where the column names are a multi-index. st.dataframe requires a dictionary specifying the column_config and expects the keys to be strings representing the column name. The problem is that the multi-index columns are not strings but tuples.

The following code illustrates the problem:

import streamlit as st
import pandas as pd
from datetime import date

df = pd.DataFrame(
    {
        ("Date", "A"): [date(2024, 1, 1), date(2024, 2, 1), date(2024, 3, 1)],
        ("Total","B"): [13429, 23564, 23452],
    }
)
st.dataframe(
    df,
    column_config={
        # FAIL: attempt to style the columns by tuple index
        # ("Date","A"):
        # Work-around: using integer index: the column index + the number of levels in the index
        1:
            st.column_config.DateColumn(format="MMM YYYY"),
    },
    hide_index=True,
)

producing error TypeError: keys must be str, int, float, bool or None, not tuple. A workaround is to use an integer index, which seems to be: the integer index of the column I am trying to config + the number of levels in the index (even when hide_index=True). Here, I am trying to config column 0 and there is 1 level in the index, so I index 1.

How can I properly specify the columns when the DataFrame has a MultiIndex? (As a side note, trying to set the label with st.column_config.Column as a tuple does not work as expected either. I think this is related to the same underlying issue.)

I am having the same issue. Now that multi-index columns are a first class citizen with the st.datafame() component, it would be great to figure out how to be able to use the column_configs with multi-index columns

2 Likes

Try aggrid dataframe editor.
https://github.com/PablocFonseca/streamlit-aggrid
This should give you the required functionality and much more. Hope it helps

This is an issue for myself as well, the solution I found was to use the integer index location in the column_configs. So if you would like to style the column with multi-index (โ€œAโ€, โ€œBโ€), use the index.get_loc() to find the location and use that integer number to style

1 Like

I think you need to take the number of levels of the index into account (i.e., the integer index changes if you have a pd.MultiIndex rather than a simple pd.Index. As stated in the OP, I believe the index you need is:
The integer index of the column I am trying to config + the number of levels in the index.