简单来说,我的目标是在我的HTML页面中显示一个表格,看起来“正常”(即所有标题都在单行上,没有行号),并且每个单元格根据规则查找进行颜色编码(需要灵活性以查找每个单元格的不同规则)。我的数据存储在pd.DataFrame对象中。有时我的数据最好表示为数据透视表(多个指数)。格式化是最终用户的要求。文件系统访问非常有限,所有这些都是多线程的,因此我没有写入HTML然后读取修改写入的选项。
关于操作环境的一些信息:
- Python 3.5.2 - Pandas版本0.19.2 - 需要在x86和x64上运行 - 需要在Windows和Linux上运行
示例设置:
指定 ['special_col_1', 'special_col_2'] 会再次破坏顶部行的格式
不指定任何列是不可接受的('ValueError:未传递分组键!')
具有 pd.DataFrame.Styler 对象的所有优点和缺点
非常感谢您的帮助!很抱歉我不能包含表格的图像,这是我的第一篇文章。
确认工作答案(piRSquared)提供了我所需要的灵活性:
关于操作环境的一些信息:
- 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()