逐行格式化熊猫数据框

Posted

技术标签:

【中文标题】逐行格式化熊猫数据框【英文标题】:Format pandas dataframe row wise 【发布时间】:2019-03-17 21:57:25 【问题描述】:

我有以下数据框并想将其转换为 html

            Limit        Status     Warning      3M AVG
VAR1        1.20         1.21216    1.11         1.21235
VAR2        0.82         0.63075    0.75         0.593295
VAR3        0.38         0.376988   0.35         0.376988
VAR4        0.17         0.126987   0.14         0.12461

我想按行格式化这个数据框:

    如果Status 超过Warning,整行变为黄色突出显示,如果超过Limit,整行变为红色突出显示 VAR2VAR3 行的格式为“:.2%”,VAR1VAR4 的格式为“:.2f”

我研究了 pandas 文档并尝试了几种方法,但我无法完成上述所有任务

如果您能提供帮助,我将不胜感激,因为我相信对许多 pandas 用户来说,明智地格式化数据框行是一个挑战。

编辑1:我试过以下代码:

df=df.transpose()    
df.style.format(":.2%").format("VAR1":":.2f,"VAR4":":.2f")

注意:通过转置数据框可以更轻松地完成所有任务,但我无法将其转回原来的形状,因为它是样式器。

【问题讨论】:

到目前为止,您到底尝试了什么?如果你有一些代码,任何东西都可以提供帮助。否则人们可能只会推荐你已经尝试过的东西。或者他们可以帮助您让他们工作。 我已经添加了我的一些代码并解释了它的局限性 【参考方案1】:

我认为您可以使用自定义 Styling 函数做您想做的事:

def color(row):
    if row.Status >= row.Limit:
        return ['background-color: red'] * len(row)
    elif row.Status >= row.Warning:
        return ['background-color: yellow'] * len(row)
    return [''] * len(row)

df.style.apply(color, axis=1)

不过,您仍然需要为此添加自定义数字格式。

要为此获取 HTML 代码,请使用 render 方法:

df.style.apply(color, axis=1).render()

<style  type="text/css" >
    #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col0 
            background-color:  red;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col1 
            background-color:  red;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col2 
            background-color:  red;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col3 
            background-color:  red;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col0 
            background-color:  yellow;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col1 
            background-color:  yellow;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col2 
            background-color:  yellow;
            #T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col3 
            background-color:  yellow;
        </style>  
<table id="T_e61b55e0_cef5_11e8_9f07_68f72880acdc" > 
<thead>    <tr> 
        <th class="blank level0" ></th> 
        <th class="col_heading level0 col0" >Limit</th> 
        <th class="col_heading level0 col1" >Status</th> 
        <th class="col_heading level0 col2" >Warning</th> 
        <th class="col_heading level0 col3" >3M AVG</th> 
    </tr></thead> 
<tbody>    <tr> 
        <th id="T_e61b55e0_cef5_11e8_9f07_68f72880acdclevel0_row0" class="row_heading level0 row0" >VAR1</th> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col0" class="data row0 col0" >1.2</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col1" class="data row0 col1" >1.21216</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col2" class="data row0 col2" >1.11</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow0_col3" class="data row0 col3" >1.21235</td> 
    </tr>    <tr> 
        <th id="T_e61b55e0_cef5_11e8_9f07_68f72880acdclevel0_row1" class="row_heading level0 row1" >VAR2</th> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow1_col0" class="data row1 col0" >0.82</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow1_col1" class="data row1 col1" >0.63075</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow1_col2" class="data row1 col2" >0.75</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow1_col3" class="data row1 col3" >0.593295</td> 
    </tr>    <tr> 
        <th id="T_e61b55e0_cef5_11e8_9f07_68f72880acdclevel0_row2" class="row_heading level0 row2" >VAR3</th> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col0" class="data row2 col0" >0.38</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col1" class="data row2 col1" >0.376988</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col2" class="data row2 col2" >0.35</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow2_col3" class="data row2 col3" >0.376988</td> 
    </tr>    <tr> 
        <th id="T_e61b55e0_cef5_11e8_9f07_68f72880acdclevel0_row3" class="row_heading level0 row3" >VAR4</th> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow3_col0" class="data row3 col0" >0.17</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow3_col1" class="data row3 col1" >0.126987</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow3_col2" class="data row3 col2" >0.14</td> 
        <td id="T_e61b55e0_cef5_11e8_9f07_68f72880acdcrow3_col3" class="data row3 col3" >0.12461</td> 
    </tr></tbody> 
</table>

【讨论】:

【参考方案2】:

我遇到了同样的问题,并查看了 pandas.io.formats.style.Styler 类中 format 函数的实现,并实现了类似的逐行函数:

def format_row_wise(styler, formatter):
    for row, row_formatter in formatter.items():
        row_num = styler.index.get_loc(row)

        for col_num in range(len(styler.columns)):
            styler._display_funcs[(row_num, col_num)] = row_formatter
    return styler

示例

df = pandas.DataFrame(
    
        'Limit': [1.20, 0.82, 0.38, 0.17], 
        'Status': [1.21216, 0.63075, 0.376988, 0.126987], 
        'Warning': [1.11, 0.75, 0.35, 0.14], 
        '3M AVG': [1.21235, 0.593259, 0.376988, 0.12461]
    , 
    index=['VAR1', 'VAR2', 'VAR3', 'VAR4']
)
formatters = "VAR1":lambda x: f"x:.2f", "VAR4": lambda x: f"x:.2f"
styler = format_row_wise(df.style, formatters)
styler.render()

这对我有用:)

注意

我只实现了 dict-formatter! 格式必须作为函数给出(这里:lambda)

希望这能让你走上正确的道路......

【讨论】:

以上是关于逐行格式化熊猫数据框的主要内容,如果未能解决你的问题,请参考以下文章

格式化熊猫数据框中整数的千位分隔符

熊猫数据框到 json 列表格式

将熊猫数据框格式更改为另一种格式?

如何根据字典中的键值逐行向熊猫数据框添加值?

如何格式化熊猫数据框并保留原始浮点精度值

将纪元时间转换为熊猫数据框中的格式化日期字符串