r.user.05apr
r.user.05apr

Reputation: 5456

Looping through pandas xlsxwriter sheet

I would like to create a conditional format in an excel-sheet using pandas. Columns A and B should be red if they are smaller than the respective value in column C. How can I accomplish that properly, and why is my loop stopping 2 rows early?

import numpy as np
import pandas as pd

d = pd.DataFrame(np.random.randint(1, 4, (15, 3)), columns = ['A', 'B', 'C'])

writer = pd.ExcelWriter('c:\\users\\MYNAME\\desktop\\xl_loop.xlsx') # please change!
d.to_excel(writer, 'Sheet1', index = False)
worksheet = writer.sheets['Sheet1']

for i in (range(d.shape[0])):
    worksheet.conditional_format(
        'A{}:B{}'.format(i, i),
        {'type': 'icon_set',
         'icon_style': '3_traffic_lights',
         'icons': [{'criteria': '>', 'type': 'number', 'value': d.iloc[i, 2]},
                    {'criteria': '=', 'type': 'number', 'value': d.iloc[i, 2]},
                    {'criteria': '<', 'type': 'number', 'value': d.iloc[i, 2]} ]} )
writer.save()

Upvotes: 3

Views: 2689

Answers (2)

jmcnamara
jmcnamara

Reputation: 41554

You have a couple of off-by-one errors in your range calculation and positioning which is why your range is 2 rows short.

However, it isn't necessary to create a conditional format for each row. You can create one for the entire range as follows:

import numpy as np
import pandas as pd

d = pd.DataFrame(np.random.randint(1, 4, (15, 3)), columns = ['A', 'B', 'C'])

writer = pd.ExcelWriter('xl_loop.xlsx')
d.to_excel(writer, 'Sheet1', index = False)

workbook  = writer.book
worksheet = writer.sheets['Sheet1']

red_format = workbook.add_format({'bg_color': '#FFC7CE',
                                  'font_color': '#9C0006'})

start_row = 1
end_row   = start_row + d.shape[0] -1
start_col = 0
end_col   = 1

worksheet.conditional_format(start_row, start_col, end_row, end_col,
    {'type': 'cell',
     'criteria': '<',
     'value': '$C2',
     'format': red_format})

writer.save()

Output:

enter image description here

Upvotes: 3

MaxU - stand with Ukraine
MaxU - stand with Ukraine

Reputation: 210832

You can use Styling:

(d.style
  .apply(lambda c: (c < d['C']).map({True:'background-color: red', False:''}))
  .to_excel('c:/temp/res.xlsx', index=False, engine='openpyxl'))

Result:

enter image description here

Upvotes: 3

Related Questions