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

如何为MultiIndex DataFrame按条件设置行的字体及背景色

解决MultiIndex DataFrame按Metric批量设置样式的问题

问题背景

已构造如下MultiIndex结构的DataFrame:

from collections import defaultdict
import pandas as pd

dic = {'US':{'Traffic':{'new':1415, 'repeat':670}, 'Sales':{'new':67068, 'repeat':105677}},
      'UK': {'Traffic':{'new':230, 'repeat':156}, 'Sales':{'new':4568, 'repeat':10738}}}
d1 = defaultdict(dict)
for k, v in dic.items():
    for k1, v1 in v.items():
        for k2, v2 in v1.items():
            d1[(k, k2)].update({k1: v2})

df = pd.DataFrame.from_dict(d1, orient='index')
df.insert(loc=2, column=' ', value=None)
df.insert(loc=0, column='Mode', value='Website')
df.columns = df.columns.rename("Metric", level=1)

需要根据以下逻辑,为Traffic和Sales对应的单元格分别设置字体颜色和背景色:

# 注意:原函数中的"light red""light orange"不是CSS标准颜色,已替换为有效颜色值
def sales_color(val):
    font_color = ''
    background_color = ''
    
    if val <= 10000:
        font_color = 'red'
        background_color = 'lightcoral'
    elif val >= 100000:
        font_color = 'green'
    else:
        font_color = 'grey'
        
    return f'color: {font_color}; background-color: {background_color}'

def traffic_color(val):
    font_color = 'orange' if val < 300 else 'black'
    background_color = 'peachpuff' if val < 300 else ''
    return f'color: {font_color}; background-color: {background_color}'

之前尝试逐个单元格应用样式的方法无效:

df['US']['new']['Sales'].style.apply(sales_color)
df['US']['new']['Traffic'].style.apply(traffic_color)
# 其他类似逐个单元格的调用...

正确实现方法

方法1:按列精准匹配Metric批量应用

利用applymap结合pd.IndexSlice,直接针对目标列批量设置样式:

def apply_style(df):
    styled_df = df.style
    # 为Traffic列应用对应样式
    styled_df = styled_df.applymap(traffic_color, subset=pd.IndexSlice[:, 'Traffic'])
    # 为Sales列应用对应样式
    styled_df = styled_df.applymap(sales_color, subset=pd.IndexSlice[:, 'Sales'])
    # 空列跳过样式设置
    styled_df = styled_df.applymap(lambda x: '', subset=pd.IndexSlice[:, ' '])
    return styled_df

# 生成带样式的结果
styled_result = apply_style(df)
# 查看效果
styled_result

方法2:通用分发函数适配多Metric

如果后续有更多Metric需要设置样式,可以写一个统一的分发逻辑:

def metric_style(val, metric):
    if metric == 'Sales':
        font_color = ''
        background_color = ''
        if val <= 10000:
            font_color = 'red'
            background_color = 'lightcoral'
        elif val >= 100000:
            font_color = 'green'
        else:
            font_color = 'grey'
        return f'color: {font_color}; background-color: {background_color}'
    elif metric == 'Traffic':
        font_color = 'orange' if val < 300 else 'black'
        background_color = 'peachpuff' if val < 300 else ''
        return f'color: {font_color}; background-color: {background_color}'
    else:
        return ''

# 按列遍历,传递列名作为判断依据
styled_df = df.style.apply(lambda col: [metric_style(v, col.name) for v in col], axis=0)
styled_df

关键注意点

  1. 样式函数必须返回CSS格式的字符串(如color: red; background-color: lightcoral),原函数返回列表的方式不符合pandas样式要求,这是之前方法无效的核心原因。
  2. 使用pd.IndexSlice可以精准定位MultiIndex中的目标列,避免逐个单元格操作的低效性。
  3. 必须使用CSS标准颜色名或十六进制颜色值,非标准颜色描述无法生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 19:01:18