我该如何根据 pandas 数据框中另一列的元素来设置某一列的元素样式?

huangapple go评论54阅读模式
英文:

How would I style a column's elements based on another column's elements in a pandas data frame?

问题

以下是您要翻译的代码部分:

import pandas as pd

# 示例数据框架
data = {
    'Greek letters': ["Alpha", "Beta", "Gamma", "Omega", "Delta"],
    'English letters': ["A", "B", "C", "D", "E"],
    'Greek Letter score': [5, 10, 15, 20, 25],
    'English Letter score': [3, 11, 12, 18, 25]
}
df = pd.DataFrame(data)

def highlight_letter(value):
    # 如何使用字母元素来获取其对应的分数?
    # 分数 = 用于获取字母分数的某种技巧
    if score <= 10:
        return 'background-color: lightgreen'
    elif score <= 20:
        return 'background-color: yellow'
    else:
        return 'background-color: blue'

styled_df = df.style.applymap(highlight_letter, subset=['Greek letters', 'English letters'])

希望这有所帮助。

英文:

Say, for example, I have a pandas data frame like so:

import pandas as pd

# Sample DataFrame
data = {
    &#39;Greek letters&#39;: [&quot;Alpha&quot;, &quot;Beta&quot;, &quot;Gamma&quot;, &quot;Omega&quot;, &quot;Delta&quot;],
    &#39;English letters&#39;: [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;],
    &#39;Greek Letter score&#39;: [5, 10, 15, 20, 25],
    &#39;English Letter score&#39;: [3, 11, 12, 18, 25]
}
df = pd.DataFrame(data)

What I want to do is apply specific background colors only to the elements in the columns Greek letters and English letters based on their respective scores (so, based on the elements in the Greek Letter score and English Letter score columns respectively).

def highlight_letter(value):
    # How would I use the letter element to obtain its corresponding score?
    # score = some technique to obtain the letter&#39;s score 
    if score &lt;= 10:
        return &#39;background-color: lightgreen&#39;
    elif score &lt;= 20:
        return &#39;background-color: yellow&#39;
    else:
        return &#39;background-color: blue&#39;

styled_df = df.style.applymap(highlight_letter, subset=[&#39;Greek letters&#39;, &#39;English letters&#39;])

This is what the expected output should look like:

我该如何根据 pandas 数据框中另一列的元素来设置某一列的元素样式?

答案1

得分: 2

实际上,您所需要的不是applymap,而是apply,沿着行进行操作。为了避免硬编码,让我们假设您至少拥有像“Something letters”和“Something Letter score”这样的一对对,无论以什么大小写和列顺序出现。考虑到这一点,我建议采用以下方法:

def highlight_letter(record):
    formatting = record.copy()
    subset = record.index.str.endswith('letters')
    formatting[~subset] = ''
    for name in formatting.index[subset]:
        score = record[name[:-1] + ' score']   # -1用于删除letters末尾的s
        formatting[name] = (
            'background-color: lightgreen' if score <= 10 else
            'background-color: yellow' if score <= 20 else
            'background-color: blue'
        )
    return formatting


styled_df = df.rename(columns=str.lower).style.apply(
    highlight_letter,
    axis='columns'
)

在您的测试数据上的输出如下所示:

更新

这是另一种情况的方式,即我们有一个固定的结构,就像前半部分的列是字母,接下来的一半是它们得分的对应列:

half = len(df.columns)//2
score = df.iloc[:, half:]

category_level = np.add(
    score <= 10,
    score <= 20,
    dtype=int     # 需要这个来累加整数,而不是布尔值
)

category_formatting = [   
    'background-color: blue',          # 默认颜色
    'background-color: lightgreen',    # <=10
    'background-color: yellow',        # <=20
]

formatting = np.choose(category_level, category_formatting)

此时,formatting是一个具有第二半部分列名的DataFrame。为了得到正确的应用,我们必须用它们的对应列名替换第一半部分的列名:

formatting.columns = df.columns[:half]
styled_df = df.style.apply(lambda _: formatting, axis=None)
英文:

Actually, what you need is not applymap but apply along the rows. To avoid hardcoding, let's assume that you have at least pairs like "Something letters" and "Something Letter score" in whatever case and column order it can be. With that in mind, I'd suggest this approach:

def highlight_letter(record):
    formatting = record.copy()
    subset = record.index.str.endswith(&#39;letters&#39;)
    formatting[~subset] = &#39;&#39;
    for name in formatting.index[subset]:
        score = record[name[:-1] + &#39; score&#39;]   # -1 to drop ending s in letters
        formatting[name] = (
            &#39;background-color: lightgreen&#39; if score &lt;= 10 else
            &#39;background-color: yellow&#39; if score &lt;= 20 else
            &#39;background-color: blue&#39;
        )
    return formatting


styled_df = df.rename(columns=str.lower).style.apply(
    highlight_letter,
    axis=&#39;columns&#39;
)

The output on your test data looks like this:
我该如何根据 pandas 数据框中另一列的元素来设置某一列的元素样式?

Update

Here's another way for the case where we have a fixed structure, like first half of columns are letters, and the next one - the corresponding columns of their scores:

half = len(df.columns)//2
score = df.iloc[:, half:]

category_level = np.add(
    score &lt;= 10,
    score &lt;= 20,
    dtype=int     # need this to accumulate integers, not booleans
)

category_formatting = [   
    &#39;background-color: blue&#39;,          # default color
    &#39;background-color: lightgreen&#39;,    # &lt;=10
    &#39;background-color: yellow&#39;,        # &lt;=20
]

formatting = np.choose(category_level, category_formatting)

At this point, formatting is a DataFrame with column names from the second half. To get the right applying, we have to replace column names with their twins from the first half:

formatting.columns = df.columns[:half]
styled_df = df.style.apply(lambda _: formatting, axis=None)

huangapple
  • 本文由 发表于 2023年7月27日 23:27:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76781298.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定