看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
像 Series 或者 DataFrame 的 apply() 和 applymap() 一样,Styler 也可以使用它们进行样式的复杂定义。
弃用预告
从 pandas 2.1 开始,使用 Styler.applymap 时会抛出弃用警告。意味着 applymap 在不久的将来将会不再支持,而会被 Styler.map 替代。
样式调用函数的方法有:
这两个方法都接受一个函数(以及一些其他关键字参数)并以某种方式将函数应用于数据帧。applymap 在 DataFrame 所有元素中有效。apply 根据 axis 关键字参数,一次将每个列或行传递到数据框中,或一次传递到整个表中。行使用 axis=0 (默认),列使用 axis=1,对于整个表,使用 axis=None。
最大值字体置为红色:
# 最大值显示红色
def highlight_max(x):
return ['color: red' if v == x.max() else '' for v in x]
# 应用函数
df.style.apply(highlight_max)
# 按行应用
df.loc[:,'Q1':'Q4'].style.apply(highlight_max, axis=1)
以下所有大于90分的格子背景为黄色:
yellow_css = 'background-color: yellow'
sfun = lambda x: yellow_css if type(x) == int and x > 90 else ''
(df.style
.applymap(sfun)
)
subset 参数可以指定部分内容应用样式规则:
(df.style
.applymap(sfun, subset=['Q1', 'Q2'])
)
subset 可传入索引器 pd.IndexSlice实现复杂逻辑下的部分区域应用:
# 筛选条件1:满足指定条件并且应用在某个列上
sst1 = pd.IndexSlice[df.loc[(df.c=='good') & (df.f>60)].index, 'f']
# 样式方法
sfun1 = lambda x: 'background-color: yellow' if x > 500 else ''
(
df.style
.applymap(sfun1, subset=sst1)
# .to_excel('gairuo.xlsx', engine='openpyxl')
)
对满足条件的行整行加背景样式:
yellow_css = 'background-color: yellow'
sfun = lambda x: [yellow_css]*len(x) if x.math > 80 else ['']*len(x)
(df.style
.apply(sfun, axis=1)
)
# 使用函数,字体颜色整行为红
def row_color(s):
if s.J > 80:
return ['color: red']*len(s)
else:
return ['']*len(s)
# 调用
df.style.apply(row_color, axis=1)
另外,style.where 可以简化 applymap 的应用,如:
df.style.where(lambda x: x > 60,
'background-color: yellow',
other='font-size: 15px',
subset=['Q1']
)
其实 style.where 是执行了以下操作:
df.style.applymap(
lambda val: value if cond(val) else other, subset=subset, **kwargs
)
# 定义样式函数
def format_conversion(styler):
return (styler.set_properties(**{'text-align': 'right'})
.format({'conversion': '{:.1%}'}))
df = pd.DataFrame({'trial': list(range(5)),
'conversion': [0.75, 0.85, np.nan, 0.7, 0.72]})
# 使用管道方法调用
(df.style
.highlight_min(subset=['conversion'], color='yellow')
.pipe(format_conversion)
.set_caption("Results with minimum conversion highlighted.")
)
可以将其他的样式利用到新的表格中:
# 将 df 的样式赋值给变量
style1 = df.style.applymap(color_negative_red)
# df2 的样式为 style2
style2 = df2.style
# style2 使用 style1的样式
style2.use(style1.export())
df.style.clear() 会返回 None
,清除所有样式。
# 定义为一个变量
dfs = df.loc[:,'Q1':'Q4'].style.apply(highlight_max)
dfs.clear() # 清除
dfs # 此时 dfs 不带任何样式,但还是 Styler 对象
当用户应用样式时(通过.apply
,.applymap
或其中一个内置函数),我们实际上不计算任何内容。相反,我们将函数和参数附加到列表self._todo
。当询问(通常在.render
中),我们将遍历列表并执行每个函数(这在self._compute()
中。这些函数更新内部defaultdict(list)
,self.ctx
,它将DataFrame行/列位置映射到CSS属性值对。
我们通过self._todo
采取额外的步骤,以便我们可以导出样式并将其设置在其他Styler上。
呈现使用Jinja模板。.translate
方法采用self.ctx
并构建另一个字典,准备传递到Styler.template.render
,Jinja 模板。
Styler._todo
中保存了要执行的函数,如:
df = pd.read_csv('https://gairuo.com/team').head()
df_style = df.style.highlight_max() # 最大值高亮
# 一个列表,所有要执行的样式函数
df_style._todo
'''
[
(<function Styler.apply.<locals>.<lambda> at 0x7f86322939d0>,
(<function Styler._highlight_extrema at 0x7f8632293670>,
0,
(slice(None, None, None), Index(['Q1', 'Q2', 'Q3', 'Q4'], dtype='object'))),
{'color': 'yellow', 'max_': True}
)
]
'''
我们看到,todo 中以列表形式存储了要执行的样式函数。
Styler._compute()
会执行Styler._todo
中的函数方法:
# 执行 self._todo 中的样式函数
df_style._compute()
# 输出样式效果
Styler.ctx
中保存了样式的原子信息,它是一个 defaultdict 字典格式数据。我们可以通过它来查询、分析、重新拼装这些信息:
# 注:需要执行计算才能更新进行 ctx,多次执行会增加到 ctx
df_style._compute()
# 查看
'''
df_style.ctx
'''
defaultdict(list,
{(3, 2): ['background-color: yellow''...],
(3, 3): ['background-color: yellow''...],
(3, 4): ['background-color: yellow''...],
(4, 5): ['background-color: yellow''...],
(0, 0): [],
(0, 1): [],
... ...
'''
其中的 (3, 2)、(4, 5) 等是样式所在的行列索引位,没有应用到样式的单元格为空。Styler.ctx
同时还有以下些有用的属性:
# ctx.items() 可以迭代以述 defaultdict 数据
for i, s in df_style.ctx.items():
print(i, s)
'''
(3, 2) ['background-color: yellow', ...]
(3, 3) ['background-color: yellow', ...]
(3, 4) ['background-color: yellow', ...]
(4, 5) ['background-color: yellow', ...]
(0, 0) []
(0, 1) []
... ...
'''
# 查询指定样式的数据
for cell, color in df_style.ctx.items():
if 'background-color: yellow' in color:
print(cell, color, df.iloc[cell])
'''
(3, 2) ['background-color: yellow'...] 93
(3, 3) ['background-color: yellow'...] 96
(3, 4) ['background-color: yellow''...] 71
(4, 5) ['background-color: yellow''...] 86
'''
# 所有的样式值
df_style.ctx.values()
# dict_values([['background-color: yellow',...], [], [], ...])
更新时间:2023-07-04 07:34:42 标签:pandas 样式 函数