Search code examples
pythonpandasstylingstreamlit

Highlight row based in streamlit


I can't seem to find any specific answers to my question as I'm not sure if it can be done with apply or applymap.

I have a parameter dataframe, lets call it x. I have a raw data frame, lets call it y.

  y = pd.DataFrame({"a": {"h":0.5,"x": 2, "y": 1}, "b": {"h":15,"x": 20, "y": 6}})
  x = pd.DataFrame({"thres1": {"x": 2, "h": 1,"y":3}, "thres2": {"x": 10, "h": 12,"y":3}})

x provides the thresholds where if certain column of raw data exceeds, will require the row to be highlighted. Note the rows in y needs to be compared to the correct rows in x given the row indexes. There can be situations where x will have more rows than y, (but not the other way around, so we need to make sure we .loc to match the correct row.

so for example, I want to compare column "b" in raw dataframe y to column 'thres2" in raw dataframe x. for the first row of y in column "b", its 15. I need to compare 15 to the second row second column of x which is 12. Because its bigger, I need to highlight that.

apply apply the entire dataframe while applymap does cell by cell. Issue is I need to do .loc before. How would styling the dataframe work for this in streamlit? (preferably without json please)

Update: I'm trying to get the row index "B" to highlight but it doesn't. Here is an example app that tries to do this:

import streamlit as st
import pandas as pd
import numpy as np


def MainDashboard():
    st.sidebar.title("Test")

    df = pd.DataFrame([[1,2], [3,4]], index=["A", "B"])
    def color_b(s):
        return np.where(s == "B", "background-color: yellow;", "")
    df.style.apply_index(color_b)
    st.dataframe(df)

if __name__ == '__main__':
    MainDashboard()

enter image description here


Solution

  • Use Styler.apply with axis=None for pass entire DataFrame, for compare need same columns and index labels, so rename x.columns by DataFrame.set_axis:

    import streamlit as st
    
    highlight_greater = lambda z: pd.DataFrame(np.where(z.gt(x.set_axis(z.columns, axis=1)),
                                              'background-color:red',
                                               ''), index=z.index, columns=z.columns)
    styled = y.style.apply(highlight_greater, axis=None)
    
    st.table(styled)
    

    IIUC use:

    highlight_greater = lambda z: np.where(y.gt(x.set_axis(z.columns, axis=1)).any(axis=1), 
                                           'background-color:red', '')
    df.style.apply_index(highlight_greater)