我有这个 df:
NOMBRE ESTACION DEPARTAMENTO ... APNoviembre APDiciembre
0 ARAMANGO AMAZONAS ... -15.463042 3.254973
1 BAGUA CHICA AMAZONAS ... -8.193005 7.855943
2 CHACHAPOYAS AMAZONAS ... -11.803714 -9.552846
3 CHIRIACO AMAZONAS ... NaN NaN
4 EL PINTOR AMAZONAS ... 8.99654 10.01199
.. ... ... ... ... ...
529 ITE TACNA ... 500.0 25.0
530 VILACOTA TACNA ... -14.666667 2.389078
531 LA CRUZ TUMBES ... -26.666667 78.125
532 LAS PALMERAS DE UCAYALI UCAYALI ... 8.700102 6.0981
533 SAN ALEJANDRO UCAYALI ... -23.723229 -24.59382
[534 rows x 20 columns]
我只想对确定范围内的数值(从9到最后一列的列)进行着色并将其导出到excel。所以我做了这个代码:
#Export the df to excel
with pd.ExcelWriter("path/to/file/df.xlsx") as writer:
df.to_excel(writer,'ANOM', index=False)
import openpyxl
from openpyxl.styles import PatternFill
import pandas as pd
wb = openpyxl.load_workbook("path/to/file/df.xlsx")
ws = wb.active #Name of the working sheet
fill_cell1 = PatternFill(patternType='solid',
fgColor='C2523C')
fill_cell2 = PatternFill(patternType='solid',
fgColor='E8951A')
fill_cell3 = PatternFill(patternType='solid',
fgColor='FAEA05')
fill_cell4 = PatternFill(patternType='solid',
fgColor='FFFFFF')
fill_cell5 = PatternFill(patternType='solid',
fgColor='B8F500')
fill_cell6 = PatternFill(patternType='solid',
fgColor='400000')
fill_cell7 = PatternFill(patternType='solid',
fgColor='19B04D')
fill_cell8 = PatternFill(patternType='solid',
fgColor='198759')
fill_cell9 = PatternFill(patternType='solid',
fgColor='089EAD')
fill_cell10 = PatternFill(patternType='solid',
fgColor='2B61A8')
fill_cell11 = PatternFill(patternType='solid',
fgColor='0B2C7A')
fill_cell12 = PatternFill(patternType='solid',
fgColor='000000')
for row in ws.rows:
for i in range(8,8+int((ws.max_column-8)/2)):
if row[i].value > 800:
row[i].fill = fill_cell11
row[int(i+(ws.max_column-8)/2)].fill = fill_cell11
elif 400 <= row[i].value <= 800:
row[i].fill = fill_cell10
row[int(i+(ws.max_column-8)/2)].fill = fill_cell10
elif 200 <= row[i].value < 400:
row[i].fill = fill_cell9
row[int(i+(ws.max_column-8)/2)].fill = fill_cell9
elif 100 <= row[i].value < 200:
row[i].fill = fill_cell8
row[int(i+(ws.max_column-8)/2)].fill = fill_cell8
elif 60 <= row[i].value < 100:
row[i].fill = fill_cell7
row[int(i+(ws.max_column-8)/2)].fill = fill_cell7
elif 30 <= row[i].value < 60:
row[i].fill = fill_cell6
row[int(i+(ws.max_column-8)/2)].fill = fill_cell6
elif 15 <= row[i].value < 30:
row[i].fill = fill_cell5
row[int(i+(ws.max_column-8)/2)].fill = fill_cell5
elif -15 <= row[i].value < 15:
row[i].fill = fill_cell4
row[int(i+(ws.max_column-8)/2)].fill = fill_cell4
elif -30 <= row[i].value < -15:
row[i].fill = fill_cell3
row[int(i+(ws.max_column-8)/2)].fill = fill_cell3
elif -60 <= row[i].value < -30:
row[i].fill = fill_cell2
row[int(i+(ws.max_column-8)/2)].fill = fill_cell2
elif -100 <= row[i].value < -60:
row[i].fill = fill_cell1
row[int(i+(ws.max_column-8)/2)].fill = fill_cell1
elif row[i].value == "NaN" or row[i].value == "" or row[i].value == None:
row[i].fill = fill_cell12
row[int(i+(ws.max_column-8)/2)].fill = fill_cell12
wb.save("path/to/file/df_colored.xlsx")
但是我得到了这个错误:
TypeError: '>' not supported between instances of 'str' and 'int'
我知道错误是因为 openpyxl 将
row[i].value
作为字符串标题,而不是数值,但我不明白为什么。我将range(8,8+int((ws.max_column-8)/2))
中的8替换为9、10甚至11,它只适用于19,但我没有得到带有颜色的excel文件。有人可以帮助我很好地理解 ws 中的行并为此提供一些解决方案。
提前致谢。
是的,您正在尝试将字符串(列标题中的文本)与给出错误的 int(第一个检查值 800)进行比较。
为什么不使用 iter_rows 并跳过第一行,这样就不用担心标题了?
但是,您还需要其他字符串值“NaN”、“”和空单元格,因此仅跳过标题并不能避免此错误。因此,如果不为字符串应用单元格颜色,则可以检查单元格值是浮点数还是整数,如果是,则检查填充颜色的范围。
注意: 使用单元格类型检查意味着将
min_row
设置为 2 是不必要的,因为标头无论如何都会被两个标准检查拒绝,但它仍然可以节省循环行。
还要注意检查单元格是 None 不要使用 '==' 语法应该是;
cell.value is None
为了减少行数,我将单元格填充颜色操作更改为使用字典和函数,而不是设置多个 PatternFill 行。
...
wb = openpyxl.load_workbook("path/to/file/df.xlsx")
ws = wb.active # Name of the working sheet
def add_colour(cell, colour):
### fill cell based on the colour key
cell.fill = PatternFill(patternType='solid', fgColor=colour)
### Create colour dictionary
colour_dict = {1: 'C2523C', 2: 'E8951A', 3: 'FAEA05', 4: 'FFFFFF',
5:'B8F500', 6: '400000', 7: '19B04D', 8: '198759',
9: '089EAD', 10: '2B61A8', 11: '0B2C7A', 12: '000000'}
### loop rows in columns skipping row 1
for row in ws.iter_rows(min_col=9, max_col=8+int((ws.max_column-8)/2), min_row=2):
for cell in row:
c_value = cell.value
### Check if the cell value is integer or float
### If so check the value range and set fill colour
if isinstance(c_value, (int, float)):
if c_value > 800:
add_colour(cell, colour_dict[11])
elif 400 <= c_value <= 800:
add_colour(cell, colour_dict[10])
elif 200 <= c_value < 400:
add_colour(cell, colour_dict[9])
elif 100 <= c_value < 200:
add_colour(cell, colour_dict[8])
elif 60 <= c_value < 100:
add_colour(cell, colour_dict[7])
elif 30 <= c_value < 60:
add_colour(cell, colour_dict[6])
elif 15 <= c_value < 30:
add_colour(cell, colour_dict[5])
elif -15 <= c_value < 15:
add_colour(cell, colour_dict[4])
elif -30 <= c_value < -15:
add_colour(cell, colour_dict[3])
elif -60 <= c_value < -30:
add_colour(cell, colour_dict[2])
elif -100 <= c_value < -60:
add_colour(cell, colour_dict[1])
### This elif is on the same level as the int float test
### If cell value is not int or float check the following strings or empty cell
elif c_value == "NaN" or c_value == "" or c_value is None:
add_colour(cell, colour_dict[12])
wb.save("path/to/file/df_colored.xlsx")