3

简而言之,我的目标是在我的 html 页面中显示一个看起来“正常”的表格(也就是所有标题都在一行上,没有行号)并且每个单元格都根据规则查找进行颜色编码(需要灵活性为每个单元格查找不同的规则。)我的数据存储在 pd.DataFrame 对象中。有时我的数据可以更好地表示为数据透视表(多个索引)。格式是最终用户的要求。文件系统访问非常有限,所有这些都是多线程的,所以我真的没有选择先写 html 然后读-修改-写。

运行环境的一些信息:

  • Python 3.5.2
  • 熊猫版本 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 函数的 dict 正确应用 css 样式
可以修改为对行和列进行迭代,并且 applymap() 仍然可以工作(需要更复杂的 lambda 函数的多级字典)

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

指定 ['special_col_1', 'special_col_2'] 再次破坏顶行的格式
不指定任何列是不可接受的('ValueError: No group keys pass!')
具有作为 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()
4

2 回答 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')]}
])

在此处输入图像描述

您可以使用 a 抑制输出;并仍然获得 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()
于 2017-08-01T22:52:56.613 回答
1

您可以将 CSS 类添加到从 df.to_html 生成的 html 中,如此处文档中所述:

classes : str or list or tuple, default None CSS class(es) to apply to the result html table

因此,对于此示例代码:

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>

现在,如果您想进一步设置样式,您需要将所有生成的带有适当 css 类的 html 包装到一个 html 页面中,并在 CSS 中定义您想要的样式。

这是使用http://materializecss.com/table.html中的 materializecss 库的样式示例

在您的代码中,您将添加 css 类tablestriped如下所示:

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>

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

于 2017-08-01T22:13:54.380 回答