pandasdataframeloopspandas-styles

How to combine 3 loop functions into 1 function


This is the example data/script I am working with. If possible, I am trying to make fewer lines of code on the last part so it looks more clean/efficient. As you can see, the block below :

    styler=(df.style
              .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:,'a']])
    )
    dfi.export(styler, f'test1_{i}.png')

is repeating two more times with different list names, df_list2 and df_list3. How can I combine three loop functions into one loop function? Any help would be greatly appreciated.

import pandas as pd
import dataframe_image as dfi

df = pd.DataFrame(data=[[-100,500,400,0,222,222], [9000,124,0,-147,54,-56],[77,0,110,211,0,222], [111,11,-600,33,0,22],[213,-124,0,-147,54,-56]])
df2 = pd.DataFrame(data=[[100,500,200,0,555,222], [5000,124,0,-147,54,50],[77,0,500,211,0,222], [-900,11,-600,33,0,22],[500,-124,0,-147,54,-56]])

df.columns = pd.MultiIndex.from_product([['x','y','z'], list('ab')])
df2.columns = pd.MultiIndex.from_product([['x','y','z'], list('ab')])

df_list1=[df]
df_list2=[df2]
df_list3=[df,df2]


def colors(i):
    if i < 0:
        return 'background: red'
    elif i > 0:
        return 'background: green'
    elif i == 0:
        return 'background: yellow'
    else:
        ''

for i, df in enumerate(df_list1):
    styler=(df.style
              .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:,'a']])
    )
    dfi.export(styler, f'test1_{i}.png')
    
for i, df in enumerate(df_list2):
    styler=(df.style
              .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:,'a']])
    )
    dfi.export(styler, f'test2_{i}.png')
    
for i, df in enumerate(df_list3):
    styler=(df.style
              .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:,'a']])
    )
    dfi.export(styler, f'test3_{i}.png')

Solution

  • Add another loop by list L, also use enumerate(L, 1) for count from 1, last change generate name of png with j variable:

    L = [df_list1, df_list2, df_list3]
    
    
    for j, df_list in enumerate(L, 1):
        for i, df in enumerate(df_list):
            styler=(df.style
                      .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:,'a']])
            )
            dfi.export(styler, f'test{j}_{i}.png')
    

    EDIT: You can zip new list:

    L = [df_list1, df_list2, df_list3]
    names = ['math', 'biology', 'music']
    
    out = zip(names, L)
    
    for j, (name, df_list) in enumerate(out, 1):
        for i, df in enumerate(df_list):
            styler=(df.style
                      .applymap(colors, subset=pd.IndexSlice[:, pd.IndexSlice[:,'a']])
            )
            dfi.export(styler,f'{name}_{i}.png')