如何将CSS格式应用于pd.DataFrame并不显示索引列

3
简单来说,我的目标是在我的HTML页面中显示一个表格,看起来“正常”(即所有标题都在单行上,没有行号),并且每个单元格根据规则查找进行颜色编码(需要灵活性以查找每个单元格的不同规则)。我的数据存储在pd.DataFrame对象中。有时我的数据最好表示为数据透视表(多个指数)。格式化是最终用户的要求。文件系统访问非常有限,所有这些都是多线程的,因此我没有写入HTML然后读取修改写入的选项。
关于操作环境的一些信息:
- Python 3.5.2 - Pandas版本0.19.2 - 需要在x86和x64上运行 - 需要在Windows和Linux上运行
示例设置:
import pandas as pd
import numpy as np
df = pd.DataFrame()
df['special_col_1'] = pd.Series([0,0,0,1,1,1])
df['special_col_2'] = pd.Series([0,1,2,0,1,2])
df['a'] = pd.Series(np.random.randn(6)).apply(lambda x: int(x*100))
df['b'] = pd.Series(np.random.randn(6)).apply(lambda x: int(x*100))
df['c'] = pd.Series(np.random.randn(6)).apply(lambda x: int(x*100))

basic_limits = {'a': lambda x: 'background-color: red' if x < 0 else 'background-color: green',\
                'b': lambda x: 'background-color: red' if x < 10 else 'background-color: green', \
                'c': lambda x: 'background-color: red' if x > 20 else 'background-color: green', \
                'special_col_1': lambda x: 'background-color: white', \
                'special_col_2': lambda x: 'background-color: white'}

我尝试过的示例及原因,为什么我不喜欢它们:

df.to_html(index=False)

一切都布局正确
无法找到为每个单元格应用css的方法

pd.pivot_table(data=df, columns=['special_col_1', 'special_col_2']).to_html(index=False)

布局不正确,第一行应包含所有标签
找不到适用于每个单元格的CSS方法

dfs = df.style
for col in df.columns:
    dfs.applymap(basic_limits[col], subset=col)

不正确的布局-不应该有行号(索引),但一旦从pd.DataFrame转换为pd.DataFrame.Styler,就找不到任何删除索引的方法。
可以使用lambda函数字典正确应用CSS样式
可以修改为迭代行和列并且applymap()仍然有效(需要一个更复杂的多级lambda函数字典)

df.pivot_table(data=df, columns=???).style(...)

指定 ['special_col_1', 'special_col_2'] 会再次破坏顶部行的格式
不指定任何列是不可接受的('ValueError:未传递分组键!')
具有 pd.DataFrame.Styler 对象的所有优点和缺点
非常感谢您的帮助!很抱歉我不能包含表格的图像,这是我的第一篇文章。
确认工作答案(piRSquared)提供了我所需要的灵活性:
df = pd.DataFrame()
dfs = df.style

#iterate through dataframe's columns, applying custom function to each cell in the column
for col in df.columns: 
    dfs.applymap(cell_based_function_dict[col], subset=col)

#apply a function to each column
col_based_function = lambda c: pd.Series(['background-color: white' if c.name in ['special_col_1', 'special_col_2'] else 'background-color: red' if x == c.max() else 'background-color: orange' if x > 0 else 'background-color: green' for x in c])
dfs.apply(col_based_function)

#define css specifics for this particular table
styler.set_table_styles([\
    {'selector': 'tr :first-child', 'props': [('display', 'none')]}, \
    {'selector': 'tr:hover td', 'props': [('background-color',  'yellow')]}, \
    {'selector': 'th, td', 'props': [('border', '1px solid black'), \
                                     ('padding', '4px'), \
                                     ('text-align', 'center')]}, \
    {'selector': 'th', 'props': [('font-weight', 'bold')]}, \
    {'selector': '', 'props': [('border-collapse', 'collapse'),\
                               ('border', '1px solid black')]} \
    ])

#all the styling appears to be tied only to this particular dataframe table, so you can easily call render() on different tables of different styles
dfs.render()

请尽量简洁明了地提问,否则人们会跳过它 ;) - phaberest
重新表述一下 - 我有两个要求,但找不到同时满足的方法:(1)所有列都必须在第一行有标签;(2)必须能够修改表格中每个单元格的CSS。 - Jigl
2个回答

2
你可以使用pd.DataFrame.style.set_table_styles
我们可以继续使用相同的样式对象并更新它。
dfs = df.style
for col in df.columns:
    dfs.applymap(basic_limits[col], subset=col)

dfs.set_table_styles([
    {'selector': 'tr :first-child',
     'props': [('display', 'none')]}
])

enter image description here

您可以使用分号;来抑制输出,但仍然可以获取HTML。
dfs = df.style
for col in df.columns:
    dfs.applymap(basic_limits[col], subset=col)

dfs.set_table_styles([
    {'selector': 'tr :first-child',
     'props': [('display', 'none')]}
]);

my_html = dfs.render()

这与MedAli的答案类似,因为它是表格的一般CSS样式...我如何使用此方法修改每个单元格的样式? - Jigl
更新了我的帖子。 - piRSquared

1
您可以按照文档中的说明,将CSS类添加到从df.to_html生成的html中:

classes:str或list或tuple,默认为None,要应用于结果HTML表的CSS类

因此,对于此示例代码:

import pandas as pd 

df = pd.DataFrame() 
df['special_col_1'] = pd.Series([0,0,0,1,1,1])
df['special_col_2'] = pd.Series([0,1,2,0,1,2])

print(df.head())

df.to_html("my_html_file.html", index=False)

你会得到以下的 HTML:

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th>special_col_1</th>
      <th>special_col_2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <td>0</td>
      <td>2</td>
    </tr>
    <tr>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
  </tbody>
</table>

现在,如果您想进一步进行样式设置,您需要将所有生成的HTML与适当的CSS类包装到一个HTML页面中,并定义您想要的样式。这里是使用materializecss库的样式示例,链接在此http://materializecss.com/table.html。在您的代码中,您将添加以下CSS类:table和striped。
import pandas as pd 

df = pd.DataFrame() 
df['special_col_1'] = pd.Series([0,0,0,1,1,1])
df['special_col_2'] = pd.Series([0,1,2,0,1,2])

print(df.head())

# using classes table and striped from materializecss library 
df.to_html("my_html_file.html", classes="table striped", index=False)

输出的 HTML 需要包含在一个 HTML 页面结构中,其中我们调用了包含 CSS 代码的 materializecss 库:

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.1/css/materialize.min.css">
</head>
<body>
<table border="1" class="dataframe table striped">
  <thead>
    <tr style="text-align: right;">
      <th>special_col_1</th>
      <th>special_col_2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <td>0</td>
      <td>1</td>
    </tr>
    <tr>
      <td>0</td>
      <td>2</td>
    </tr>
    <tr>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <td>1</td>
      <td>1</td>
    </tr>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
  </tbody>
</table>
</body>
</html>

运行代码片段以查看表格的样式。

我不明白在to_html()中使用“classes”变量如何回答我的问题。那会改变整个表格的外观。我可以通过放弃第一行包含所有标签的要求来正确着色每个单元格,或者我可以使用to_html()函数正确显示表格,但是然后我无法访问表格中的每个单独单元格。 - Jigl
我在阅读你的示例时遇到了困难,不知道如何导入CSS类,以便Pandas在使用“classes”选项时能够使用它们。你可以详细介绍一下如何从materializecss中使这些类可用于Pandas吗? - sparrow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接