使用 .apply 有条件地为 pandas 数据框中的特定单元格着色

Use .apply to conditionally color specific cell in pandas dataframe

我有一个包含几列的 pandas 数据框。我正在尝试为其中一列中的单元格着色,到目前为止我已经部分成功了。

color_me栏我要:

  1. 对于除最后一行以外的所有行,我将根据特定比例着色
  2. 在该列的最后一行(因此,只有一个单元格),我想根据另一个比例进行着色。它是该列的第 9 行。

我能做到 1.,但我做不到 2。如果我必须对它应该具有的颜色设置条件,我不知道如何只突出显示一个特定的单元格。

df = pd.DataFrame({'metric': ['metric0', 'metric1', 'metric2', 'metric3', 'metric4', 'metric5', 'metric6', 'metric7', 'metric8', 'metric9'],
                  'column1': [80, 12, 110, 100.2, 39, 29, 48, 78, 93, 100.8],
                  'color_me': [89, 102, 43, 112, 70, 38, 80, 110, 93, 100.3]})

def highlight_SLA(series):
    green = 'background-color: lightgreen'
    yellow = 'background-color: yellow'
    pink = 'background-color: pink'
    return [green if value <= 90 else yellow if value <100 else pink for value in series]

def highlight_specific_cell(series):
    green = 'background-color: lightgreen'
    yellow = 'background-color: yellow'
    pink = 'background-color: pink'
    return [green if value >= 100.2 else yellow if value >100 else pink for value in series]


slice_SLA = ['color_me']

slice_SLA_index = ['color_me'][9]


(df.style

     .apply(highlight_SLA, subset = slice_SLA)
 
     .apply(highlight_SLA_availability_index, subset = slice_SLA_index)
       )

第二个 apply 不符合我的要求。它应该为值为 100.3.

的 提供绿色背景

我应该 select 它的子集吗?看来 slice_SLA_index = ['color_me'][9] 不是办法,但我不知道如何解决这个问题。

问题的目的是在编码时理解我们只想为特定列的特定行设置特殊颜色作为背景色。对于我们传递特定列的列,我们按条件创建一个背景颜色列表,创建一个空白系列,然后将该颜色设置在我们想要放置的位置。使该样式适应原始数据框。此代码的原始版本已从此答案更改为一系列以适应 .

import numpy as np
import pandas as pd

np.random.seed(0)
df = pd.DataFrame([np.random.randint(50, 150, 4) for _ in range(10)], columns=['A','B','C','D'])

def highlight_SLA(series):
    green = 'background-color: lightgreen'
    yellow = 'background-color: yellow'
    pink = 'background-color: pink'
    return [green if value <= 90 else yellow if value <100 else pink for value in series]

def highlight_specific_cell(x):
    idx = 9
    green = 'background-color: lightgreen'
    yellow = 'background-color: yellow'
    pink = 'background-color: pink'
    color = [green if v >= 100.2 else yellow if v >100 else pink for v in x]
    xx = pd.Series('', index=x.index)
    xx.loc[idx] = color[idx]
    return xx

slice_SLA = ['A']
slice_SLA_index = ['B']

(df.style.apply(highlight_SLA, subset=slice_SLA)
.apply(highlight_specific_cell, subset=slice_SLA_index))

除列之外仅修改特定行的最简单方法是通过索引两个轴来使 subset 更具限制性。标准方法是使用 IndexSlice.

而不是:

slice_SLA_index = ['color_me'][9]

制作 2D IndexSlice:

slice_SLA_index = pd.IndexSlice[9, 'color_me']

这里的9是行索引号,color_me是列名,不过subset可以根据需要扩展。

slice_SLA = ['color_me']
slice_SLA_index = pd.IndexSlice[9, 'color_me']

(
    df.style
        .apply(highlight_SLA, subset=slice_SLA)
        .apply(highlight_specific_cell, subset=slice_SLA_index)
)

*请注意索引 9 color_me 是绿色的,因为 highlight_specific_cell 规则而不是粉红色 (highlight_SLA) 规则。


可以使用标准 loc 索引规则修改 subset。例如,column1color_me 中的第 7-9 行可以按以下方式 subset

slice_SLA = ['color_me']
slice_SLA_index = pd.IndexSlice[7:9, ['column1', 'color_me']]

(
    df.style
        .apply(highlight_SLA, subset=slice_SLA)
        .apply(highlight_specific_cell, subset=slice_SLA_index)
)


作为一般改进,np.select 是比列表理解更常见的 multi-condition 映射解决方案:

import numpy as np

def highlight_SLA(series):
    green = 'background-color: lightgreen'
    yellow = 'background-color: yellow'
    pink = 'background-color: pink'
    return np.select(
        condlist=[series <= 90, series < 100],
        choicelist=[green, yellow],
        default=pink
    )


def highlight_specific_cell(series):
    green = 'background-color: lightgreen'
    yellow = 'background-color: yellow'
    pink = 'background-color: pink'
    return np.select(
        condlist=[series >= 100.2, series > 100],
        choicelist=[green, yellow],
        default=pink
    )