1

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')
2
  • A bit unusual to see Positive values in RED and Negative values in GREEN. I assume you have your reasons, however, I believe this breaks colour theory :) Commented Dec 14, 2022 at 7:56
  • 1
    Hey ScottC, yeah sorry I just made it up for the purpose of creating a sample code. Commented Dec 14, 2022 at 8:01

1 Answer 1

1

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')
Sign up to request clarification or add additional context in comments.

5 Comments

Hi jezrael, this works perfectly! Thanks as always. Is it possible to assign different names for each list, instead of 'test'? So for example, df_list1 with math{i}, df_list2 with biology{i}, and df_list3 with music{i}?
You could have your names in a list (strings) and apply the same logic ie. f'{names[j]}{j}_{i}.png' where names = ['math', 'biology', 'music']
You mean like creating a dictionary and wrapping it around? for example,file_names = {0: 'math', 1: 'biology', 2:'Diabetes', 3:'music'} f'test{file_names[i]}) something like this?
@yeppi - Answer was edited, can you test? Btw, last column solution working well in my opinion
Thanks so much, jezrael! I may have to post another question to clarify what is being asked. Your answer already provided so much insight.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.