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

如何为多层索引Pandas DataFrame列应用条件颜色样式

多层索引Pandas DataFrame条件着色适配方案

问题说明

  • 已有可正常运行的单层索引DataFrame条件着色逻辑,需要适配新增一级summary表头的MultiIndex列DataFrame,着色规则保持不变,仅新增一级顶部表头。
  • 原单层索引DataFrame结构:
Value       Limit    Actual
Issues      < 33     0
Rating      > 4      4.2
Complaints  < 15     18
Time        30 - 45  41
Tip         --       -
  • 多层索引构造代码:
df.columns = pd.MultiIndex.from_product([['summary'], df.columns])
  • 构造完成的多层索引DataFrame结构:
summary
Value       Limit    Actual
Issues      < 33     0
Rating      > 4      4.2
Complaints  < 15     18
Time        30 - 45  41
Tip         --       -
  • 原单层索引用的着色函数直接运行会触发KeyError,尝试通过pd.IndexSlice修改列引用未生效。原函数代码如下:
import re

def highlight(row):
    numbers = re.findall('[0-9]+', row['Limit'])
    if row['Value'] in ('Issues','Rating','Complaints'):
        if '>' in row['Limit'] and row['Actual'] > numbers[0]:
            color = 'green'
        elif row['Actual'] < numbers[0]:
            color = 'green'
        else:
            color = 'red'
    else:
        if len(numbers) == 0:
            color = 'yellow'
        elif row['Actual'] > numbers[0] and row['Actual'] < numbers[1]:
            color = 'green'
        else:
            color = 'red'
    return f"background-color: {color}"

适配方案

核心问题是MultiIndex列按行遍历传入的行对象,索引为多层元组,直接传入二级列名无法匹配到对应字段;同时原函数存在逻辑缺口:未区分</>阈值符号、非数值行无异常处理、返回单一样式会给整行着色。
修改后完整可运行代码如下:

import pandas as pd
import re

#  --------------------------
#  测试数据构造(已有df可跳过)
#  --------------------------
data = [
    ["Issues", "< 33", 0],
    ["Rating", "> 4", 4.2],
    ["Complaints", "< 15", 18],
    ["Time", "30 - 45", 41],
    ["Tip", "--", "-"]
]
df = pd.DataFrame(data, columns=["Value", "Limit", "Actual"])
df.columns = pd.MultiIndex.from_product([['summary'], df.columns])

#  --------------------------
#  修改后的着色函数
#  --------------------------
def highlight(row):
    # 多层列需传入完整层级元组取值
    limit_val = row[('summary', 'Limit')]
    value_type = row[('summary', 'Value')]
    actual_val = row[('summary', 'Actual')]

    # 提取阈值数值
    numbers = re.findall('[0-9]+', str(limit_val))
    # 非数值Actual直接返回黄色背景
    try:
        actual_num = float(actual_val)
    except (ValueError, TypeError):
        return ["", "", "background-color: yellow"]

    # 单阈值判断逻辑(Issues/Rating/Complaints行)
    if value_type in ('Issues','Rating','Complaints'):
        threshold = float(numbers[0])
        if '>' in limit_val and actual_num > threshold:
            color = 'green'
        elif '<' in limit_val and actual_num < threshold:
            color = 'green'
        else:
            color = 'red'
    # 区间阈值判断逻辑(Time行)
    else:
        if len(numbers) < 2:
            color = 'yellow'
        low = float(numbers[0])
        high = float(numbers[1])
        color = 'green' if low < actual_num < high else 'red'
    
    # 返回长度与列数一致的样式列表,仅给Actual列加背景色
    return ["", "", f"background-color: {color}"]

#  --------------------------
#  应用样式
#  --------------------------
styled_df = df.style.apply(highlight, axis=1)
# 在Jupyter类环境中直接渲染styled_df即可查看效果

关键修改点

  • 列引用适配:所有行内字段取值改为传入完整多层列元组,解决KeyError问题。
  • 逻辑补全:明确区分</>阈值判断规则,修复原函数大于号场景下逻辑判断遗漏的问题。
  • 异常兼容:增加Actual值转数值的异常捕获,适配Tip行这类无有效数值的场景。
  • 样式返回优化:返回等长样式列表,仅给Actual列添加背景色,其余列保持默认样式,和预期效果完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 09:03:51