pandas:带条件格式的HTML输出
我正在尝试格式化一个表格,让每一列的数据根据它们的值以不同的样式显示(就像电子表格软件里的条件格式一样)。我该如何在pandas中使用HTML格式化器来实现这个呢?
一个常见的用例是突出显示表格中的重要值。例如:
correlation p-value
0 0.5 0.1
1 0.1 0.8
2 0.9 *0.01*
pandas允许为HTML输出定义自定义格式化器——要得到上面的效果,可以使用:
import pandas as pd
from pandas.core import format
from StringIO import StringIO
buf = StringIO()
df = pd.DataFrame({'correlation':[0.5, 0.1,0.9], 'p_value':[0.1,0.8,0.01]})
fmt = format.DataFrameFormatter(df,
formatters={'p_value':lambda x: "*%f*" % x if x<0.05 else str(x)})
format.HTMLFormatter(fmt).write_result(buf)
不过,我想要改变重要值的样式(比如,使用粗体字)。
一个可能的解决方案是给HTML输出中的<td>
标签添加一个CSS类,然后通过CSS样式表来格式化它。这样就可以变成:
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>correlation</th>
<th>p_value</th>
</tr>
</thead>
<tbody>
<tr>
<td>0</td>
<td> 0.5</td>
<td> 0.10</td>
</tr>
<tr>
<td>1</td>
<td> 0.1</td>
<td> 0.80</td>
</tr>
<tr>
<td>2</td>
<td> 0.9</td>
<td class='significant'> 0.01</td>
</tr>
</tbody>
</table>
编辑:正如@Andy-Hayden所建议的,我可以通过简单地用<span class="signifcant">...</span>
替换星号来添加格式:
import pandas as pd
from StringIO import StringIO
buf = StringIO()
significant = lambda x: '<span class="significant">%f</span>' % x if x<0.05 else str(x)
df = pd.DataFrame({'correlation':[0.5, 0.1,0.9], 'p_value':[0.1,0.8,0.01]})
df.to_html(buf, formatters={'p_value': significant})
较新版本的pandas会转义这些标签。为了避免这个问题,可以将最后一行替换为:
df.to_html(buf, formatters={'p_value': significant}, escape=False)
2 个回答
8
自从pandas 0.17.1版本以来,我们可以很简单地给数据框的HTML显示加上自定义的格式,这个功能是通过样式API实现的。
import pandas as pd
df = pd.DataFrame({
'correlation':[0.5, 0.1,0.9],
'p_value':[0.1,0.8,0.01]})
styled_df = df.style.apply(
lambda x: ['font-weight: bold; background-color: yellow'
if value <= 0.01 else '' for value in x])
styled_df
在像Jupyter Notebook这样的界面中,输出会自动呈现出来,而我们也可以用render()
这个方法来获取HTML的字符串表示。
print(styled_df.render())
<style type="text/css" >
#T_4e49b9da_8451_11e8_9166_605718a99a7frow2_col1 {
font-weight: bold;
background-color: yellow;
font-weight: bold;
background-color: yellow;
}</style>
<table id="T_4e49b9da_8451_11e8_9166_605718a99a7f" >
<thead> <tr>
<th class="blank level0" ></th>
<th class="col_heading level0 col0" >correlation</th>
<th class="col_heading level0 col1" >p_value</th>
</tr></thead>
<tbody> <tr>
<th id="T_4e49b9da_8451_11e8_9166_605718a99a7flevel0_row0" class="row_heading level0 row0" >0</th>
<td id="T_4e49b9da_8451_11e8_9166_605718a99a7frow0_col0" class="data row0 col0" >0.5</td>
<td id="T_4e49b9da_8451_11e8_9166_605718a99a7frow0_col1" class="data row0 col1" >0.1</td>
</tr> <tr>
<th id="T_4e49b9da_8451_11e8_9166_605718a99a7flevel0_row1" class="row_heading level0 row1" >1</th>
<td id="T_4e49b9da_8451_11e8_9166_605718a99a7frow1_col0" class="data row1 col0" >0.1</td>
<td id="T_4e49b9da_8451_11e8_9166_605718a99a7frow1_col1" class="data row1 col1" >0.8</td>
</tr> <tr>
<th id="T_4e49b9da_8451_11e8_9166_605718a99a7flevel0_row2" class="row_heading level0 row2" >2</th>
<td id="T_4e49b9da_8451_11e8_9166_605718a99a7frow2_col0" class="data row2 col0" >0.9</td>
<td id="T_4e49b9da_8451_11e8_9166_605718a99a7frow2_col1" class="data row2 col1" >0.01</td>
</tr></tbody>
</table>
27
你可以使用数据框(DataFrame)的 to_html
方法,这个方法有一个叫 formatters
的参数。
一个更简单的办法是用 <span class="significant">
和 </span>
来包裹内容,而不是用 *
。注意:默认情况下,这些标签会被转义(也就是说 <
会变成 <
),所以你需要使用 escape=False
这个参数。