You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame按条件设单元格背景色并导出HTML报错求助

解决Pandas Styler背景色设置及HTML保存报错问题

问题背景

拥有一个包含6个分类列和6个日期数值列的Pandas DataFrame,示例如下:

import pandas as pd
import numpy as np

df = pd.DataFrame({'DIVISION': ['FRA', 'FRA', 'FRA', 'FRA', 'FRA'],
                   'MONTH': ['FEB', 'FEB', 'FEB', 'FEB', 'FEB'],
                   'YEAR': [2023, 2023, 2023, 2023, 2023],
                   'RANGE': ['C', 'C', 'C', 'C', 'I'],
                   'CABIN': ['C', 'C', 'M', 'M', 'C'],
                   'BP_TYPE': ['SYS', 'USR', 'SYS', 'USR', 'SYS'],
                   '2023-01-27': [60.92, 64.89, 112.47, 112.47, 779.78],
                   '2023-01-28': [63.18, 66.76, 132.17, 132.17, 763.60],
                   '2023-01-29': [61.95, 64.94, 129.21, 129.21, 753.88],
                   '2023-01-30': [59.40, 62.09, 118.04, 118.04, 720.08],
                   '2023-01-31': [52.69, 55.53, 104.28, 104.28, 687.73],
                   '2023-02-01': [85.56, 89.64, 123.53, 124.62, 789.50]})

需求说明

从第7列(索引为6)开始,根据当前列与前一列的偏差百分比设置单元格背景色,规则如下:

  • 偏差 > +5%: 红色
  • 偏差 < -5%: 蓝色
  • 偏差 > +2.5% 且 <= +5%: 浅红色
  • 偏差 < -2.5% 且 >= -5%: 浅蓝色

尝试过的失败方法

方法1:自定义颜色函数并按行应用

def color_cell(val):
    color = 'green'
    if val > 0:
        if val > 0.01:
            color = 'red'
        elif val > 0.025:
            color = 'lightred'
    elif val < 0:
        if val < -0.01:
            color = 'blue'
        elif val < -0.025:
            color = 'lightblue'
    return 'background-color: %s' % color

df_style = df.style.apply(color_cell, axis=1, subset=pd.IndexSlice[:, 6:])

方法2:直接对数值列应用样式

df_style = df_pivot.iloc[:, 6:].style.applymap(color_cell).render()

错误的HTML保存代码

html_content = df_style.render().to_html()
with open("color.html", "w") as f:
    f.write(html_content)

参考代码及报错

使用参考代码时出现AttributeError:

bins = np.array([-np.inf, -5, -2.5, 2.5, 5, np.inf])/100
labels = ['background-color: blue', 'background-color: lightblue', '', 'background-color: lightred', 'background-color: red']

def color(df):
    return (df.drop(columns=['DIVISION', 'MONTH', 'YEAR', 'RANGE', 'CABIN', 'BP_TYPE'])
              .pct_change(axis=1).apply(lambda s: pd.cut(s, bins=bins, labels=labels), )
              .reindex_like(df)
            )

html = (df.style.apply(color, axis=1, subset=df.columns[7:]).to_html())

with open('table.html', 'w') as f:
    f.write(html)

错误信息:

Traceback (most recent call last):
File "./test.py", line 28, in 
html = (df.style.apply(color, axis=1, subset=df.columns[7:]).to_html())
AttributeError: 'Styler' object has no attribute 'to_html'

解决方案

核心问题分析

  1. to_html()方法错误:Pandas的Styler对象没有to_html()方法,正确获取HTML字符串的方法是render()。
  2. 样式应用逻辑问题:之前的apply方式没有正确关联偏差百分比与单元格,需要先计算每行的偏差率,再针对数值列应用颜色规则。

正确代码实现

import pandas as pd
import numpy as np

df = pd.DataFrame({'DIVISION': ['FRA', 'FRA', 'FRA', 'FRA', 'FRA'],
                   'MONTH': ['FEB', 'FEB', 'FEB', 'FEB', 'FEB'],
                   'YEAR': [2023, 2023, 2023, 2023, 2023],
                   'RANGE': ['C', 'C', 'C', 'C', 'I'],
                   'CABIN': ['C', 'C', 'M', 'M', 'C'],
                   'BP_TYPE': ['SYS', 'USR', 'SYS', 'USR', 'SYS'],
                   '2023-01-27': [60.92, 64.89, 112.47, 112.47, 779.78],
                   '2023-01-28': [63.18, 66.76, 132.17, 132.17, 763.60],
                   '2023-01-29': [61.95, 64.94, 129.21, 129.21, 753.88],
                   '2023-01-30': [59.40, 62.09, 118.04, 118.04, 720.08],
                   '2023-01-31': [52.69, 55.53, 104.28, 104.28, 687.73],
                   '2023-02-01': [85.56, 89.64, 123.53, 124.62, 789.50]})

# 计算数值列的偏差百分比(当前列/前一列 -1)
numeric_cols = df.columns[6:]
pct_changes = df[numeric_cols].pct_change(axis=1)

# 定义颜色映射函数
def get_bg_color(pct):
    if pd.isna(pct):  # 第一列没有前一列,返回空样式
        return ''
    if pct > 0.05:
        return 'background-color: red'
    elif 0.025 < pct <= 0.05:
        return 'background-color: lightcoral'  # lightred不是标准CSS色,用lightcoral替代
    elif pct < -0.05:
        return 'background-color: blue'
    elif -0.05 <= pct < -0.025:
        return 'background-color: lightblue'
    else:
        return ''

# 应用样式:对每个数值列(从第7列开始)的单元格,根据偏差率设置背景色
df_style = df.style.applymap(lambda val, col: get_bg_color(pct_changes.loc[val.name, col]), 
                             subset=numeric_cols,
                             col=df.columns)

# 保存为HTML文件
html_content = df_style.render()
with open('color_table.html', 'w') as f:
    f.write(html_content)

代码说明

  1. 偏差率计算:用pct_change(axis=1)计算每行中当前列与前一列的百分比变化,得到偏差率DataFrame。
  2. 颜色函数:处理NaN值(第一列无前置列),并根据偏差率范围返回对应的CSS背景色样式,注意lightred不是标准CSS颜色,改用lightcoral保证显示正常。
  3. 样式应用:使用applymap遍历每个数值单元格,结合对应的偏差率值返回样式,subset指定仅处理第7列及以后的数值列。
  4. HTML保存:调用Styler.render()获取完整的HTML字符串,直接写入文件即可。

内容的提问来源于stack exchange,提问作者Glammy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 10:01:44