Reduce the redundancy in my pandas highlight function After a lot of browsing and experimenting I have managed to achieve to read excel file as a Dataframe, apply some style to it and export it to html. My main concern is that the highlight_max function looks a bit redundant. The rows I want to highlight are already predetermined and are not just simply minimum or maximum. I tried to do it with list comprehension but it did not work. Is it possible to return the style value with just one line?

import pandas as pd

def highlight_max(s):    
    truth = []
    for i in (df.index):
        truth.append(i in [634, 636, 638, 640, 642, 644, 648, 649, 650, 651, 656])
    return ['background-color: yellow' if v else '' for v in truth]

df = pd.read_excel('N:\Temp\filename.xlsx', index_col=False) 
df.reset_index(drop=True, inplace=True)
html = df.style.set_table_styles([{'selector': 'th,td', 'props': [('border-style','solid'),
('border-width','1px')]}]).apply(highlight_max).hide_index().render(index=False)
with open('N://temp//test.html', 'w') as f:
    f.write(html)
Your highlight_max function can be simplified a bit by passing the rows to mark as an argument (possibly with a default value), and putting it all into a list comprehension right away:

def highlight_max(column, to_mark):    
    return ['background-color: yellow' if i in to_mark else '' for i in column.index]


Note that this takes the actual column as input. Yours took the df from the global scope, disregarding the input, which means that all things you did before the apply will probably be ignored.

Use it like this:

ROWS = {634, 636, 638, 640, 642, 644, 648, 649, 650, 651, 656}

if __name__ == "__main__":
    df = pd.read_excel('N:\Temp\filename.xlsx', index_col=False) 
    df.reset_index(drop=True, inplace=True)
    styles = [{'selector': 'th,td',
               'props': [('border-style','solid'), ('border-width','1px')]}]
    html = df.style.set_table_styles(styles)\
             .apply(highlight_max, to_mark=ROWS)\
             .hide_index()\
             .render(index=False)

    with open('N://temp//test.html', 'w') as f:
        f.write(html)


I also made ROWS a set instead of a list for faster checking of in (not that it matters too much for such a small list, but it will if it gets bigger), used a style that makes the long chain of functions for html easier to read IMO, used the fact that any additional parameters passed to apply are passed along to the function to pass the rows to mark and wrapped the main code under a if __name__ == "__main__": guard to allow importing from this script without it running.