【发布时间】:2020-08-15 19:10:41
【问题描述】:
我有一个数据框,我想为其设置一些行的样式,这些行的索引出现在字典中。 在用 apply、applymap、subset with row/column/IndexSlice 尝试了一堆东西之后,我仍然没有找到解决方案
- 根据多个条件使用不同的颜色为特定行设置不同的单元格样式。 (由于需要以相同的方式将行和列写入 excel,因此转置不起作用(?!))
- 将特定行/“猫”的样式条件和颜色分组到 1 个函数中。
- 根据另一行中单元格的值有条件地设置行中所有单元格的样式,但同一列(参考所需结果)。
注意:有些行会被“样式化”,有些则不会。
第一个问题:cat1 出现在字典中,所以我需要使用条件对其进行样式设置。我需要通过条件传递行中的每个单元格以应用某种颜色。 经过大量尝试后,下面的代码“最接近”潜在的解决方案,但在保存到 Excel 时出现错误。 (当我只使用“绿色”的代码时,它确实可以正常工作)。
"DataFrame 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。"
d_functions_colors={'cat1': catone_color,'cat5': catfive_color, 'cat40':catforty_color}
2020-12 2019-12 2018-12 2017-12 2016-12 ...
idx
cat1 100 NaN 50 35 5 ...
cat2 5 NaN 7 3 2 ...
cat3 6.25 NaN 6.25 4.93 5.21 ...
avg_cat3 5 4 3 2 1 ...
max_cat3 10 20 10 30 1 ...
cat4 ...
cat5 5 20 8 9.5 25 ...
avg_cat5 10 15 8 9.5 20 ...
...
(the results for avg, max are calculated and added for some 'cats' beforehand based on multiple (other) data sources)
def highlight_row_green(x):
c0 = ''
c1 = 'background-color: green'
c2 = 'background-color: yellow'
c3 = 'background-color: red'
df1 = pd.DataFrame('', index=x.index, columns=x.columns)
m1 = x.index.astype(str).str.contains('^cat1')
mask = (x[m1] >= 50).reindex(x.index, fill_value=False)
df1 = df1.mask(mask, c1)
return df1
def highlight_row_yellow(x):
c0 = ''
c1 = 'background-color: green'
c2 = 'background-color: yellow'
c3 = 'background-color: red'
df1 = pd.DataFrame('', index=x.index, columns=x.columns)
m1 = x.index.astype(str).str.contains('^cat1$')
mask = (20 <= x[m1] < 50)
df1 = df1.mask(mask, c2)
return df1
def highlight_row_red(x):
c0 = ''
c1 = 'background-color: green'
c2 = 'background-color: yellow'
c3 = 'background-color: red'
df1 = pd.DataFrame('', index=x.index, columns=x.columns)
m1 = x.index.astype(str).str.contains('^cat1$')
mask = ( x[m1] < 20)
df1 = df1.mask(mask, c3)
return df1
def pandastoExcel(path,filename,sheetname,my_dataframe):
outputfilepath=(path+'\\'+filename)
if len(sheetname)>=30:
sheetname='Default'
else:
pass
writer = pd.ExcelWriter(outputfilepath , engine='xlsxwriter')
try:
my_dataframe.to_excel(writer, sheet_name=sheetname,index=True)
except Exception as e:
print(str(e))
writer.save()
df_output=df.style.\
apply(highlight_row_green, axis=None).\
apply(highlight_row_yellow, axis=None).\
apply(highlight_row_red, axis=None)
第二个问题:我尝试将它们分组,但得到相同的错误 "DataFrame 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。"
def catone_color(x):
c1 = 'background-color: green'
c2 = 'background-color: yellow'
c3 = 'background-color: red'
c0 = ''
df1 = pd.DataFrame('', index=x.index, columns=x.columns)
m1 = x.index.astype(str).str.contains('^cat1$')
mask = (x[m1] >= 50).reindex(x.index, fill_value=False)
masky = (20 <= x[m1] < 50)
maskr = (x[m1] < 20)
df1 = df1.mask(mask, c1)
df1 = df1.mask(masky, c2)
df1 = df1.mask(maskr, c3)
return df1
df_output=df.style.apply(catone_color, axis=None)
第三期:(例如 cat5),样式基于 cat5_avg 中的值。所以 2020 cat5_value 的颜色是基于 2020 cat5_avg 的,2019 cat5_value 的颜色是基于 2019 cat5_value 等等。
尝试通过将数据框中的 2 行(例如 row_values、row_avg)和其他一些东西结合起来,但远未取得任何成果。
2020-12 2019-12 2018-12 2017-12 2016-12 ...
idx
cat1 100 NaN 50 35 5 ...
cat2 5 NaN 7 3 2 ...
cat3 6.25 NaN 6.25 4.93 5.21 ...
avg_cat3 5 4 3 2 1 ...
max_cat3 10 20 10 30 1 ...
cat4 ...
cat5 5 20 8 9.5 25 ...
avg_cat5 10 15 8 9.5 20 ...
...
#Idea of what I'm trying to accomplish:
for cat5_value in row_cat_5:
If cat5_value > avg_cat5_same column:
color = 'green'
elif cat5_value == avg_cat5_same_column:
color = 'yellow'
elif cat5_value < avg_cat5_same_column:
color = 'red'
else:
color=''
return 'background-color: %s' % color
#(Background color row cat_5 would be red,green,yellow,yellow,green).
#What I've got left from trying:
g= 'green'
y = 'yellow'
r = 'red'
m1 = val.iloc[0, :] < val.iloc[1, :]
m2 = val.iloc[0, :] == val.iloc[1, :]
m3 = val.iloc[0, :] > val.iloc[1, :]
df1 = pd.DataFrame('background-color: ', index=val.index, columns=val.columns)
df1.iloc[:,0] = np.where(m1, 'background-color: {}'.format(g), df1.iloc[0, :])
df1.iloc[:,0] = np.where(m2, 'background-color: {}'.format(y), df1.iloc[0, :])
df1.iloc[:,0] = np.where(m3, 'background-color: {}'.format(r), df1.iloc[0, :])
return df1
提前谢谢你,
PS:早期感谢所有贡献者,他们的答案作为上述结果代码的基础。
【问题讨论】:
标签: python-3.x pandas dataframe pandas-styles