分享

浅谈 Pandas 样式

 北方的白桦林 2020-05-18



原文链接: 

https:///styling-pandas.html

简介

大家都知道 Excel 可以设定单元格格式,还支持单元格迷你图,其实 Pandas 也可以,本文参照 Chris Moffitt 的 Stylin’ with Pandas 一文,为大家简单介绍一下 Pandas 如何实现 DataFrame 的样式设置,主要内容如下:

  1. 设置 DataFrame 不同列的样式,如千分号、小数位数、货币符号、日期格式,百分比等;

  2. 突出显示 DataFrame 中某一列里符合某些条件的数据,如,按不同颜色显示某列中的最大值与最小值;

  3. 以不同渐变色展示每一行数据占总数据的比例大小,占比越大,颜色越深,占比越小,则颜色越浅;

  4. 实现类似 Excel 迷你条形图的功能,根据数据大小,在单元格里显示迷你条形图;

  5. 利用 Sparklines 支持库,配合 Pandas 绘制迷你走势图。需要先用 pip install sparklines 命令安装 Sparklines 支持库。

什么是样式?为什么与使用样式?

样式的基本理念是用户在调整数据显示形式的同时,不会影响数据本身的计算操作。

最直观的样式是货币符号,如果只显示一个数字,比如 25.06,读者并不清楚这个数字代表的到底是美元、英镑、日元还是人民币,但 ¥25.06,大家就都知道这是人民币了,由此可见,样式可以让数据提供更多信息。

百分比也是数据样式的重要形式,0.12 就不如 12% 更直观,用百分比说明数据更清晰,也更简单。

Pandas 支持不同样式,可以用更易理解的方式显示数据,但并未修改数据的类型,所以依然还可以用 Pandas 提供的各种数学、日期、字符串函数处理数据。

Pandas 样式还包括内容里提及的高级样式,比如添加颜色与条形图等可视化元素。本文只是简要介绍 Pandas 样式的基本功能,方便大家快速上手,提高数据分析报表的可读性。

数据文件说明

  1. 数据文件为 2018年销售汇总表.csv(见下方链接),本文件引用的是原文作者 Chris 虚构的一家企业 2018 年的销售数据,但汉化了数据表的标题,方便大家在代码中识别数据列的信息;

https://github.com/jaystone776/pandas_styling/blob/master/2018年销售汇总表.csv

  1. 文件格式从原文的 xlsx 改为 csv

  2. 文件共有 5 列,分别为账号(字符串)、姓名(字符串)、单品(字符串)、数量(整数)、单价(2 位小数)、金额(2 位小数)、日期(DateTime)

Jupyter Notebook 示例文件:

https://github.com/jaystone776/pandas_styling/blob/master/浅谈Pandas样式.ipynb

0.1 导入 Numpy 与 Pandas

import numpy as np

import pandas as pd

下面的代码与原文不同,原文用的是 xlsx 文件,本文用的是 csv 文件,需要解析日期。

另外需要注意,数据文件与 ipynb 文件要在同一文件夹下。

df = pd.read_csv('2018年销售汇总表.csv',parse_dates=['日期'])

0.2 df.head() 预览数据


df.head()


0.3 汇总数据,根据客人姓名分组计算 2018 年每个客人的平均金额与消费总额

df.groupby('姓名')['金额'].agg(['mean','sum'])


汇总统计消费金额

1.1 设置金额样式:货币符号、千分号、2 位小数

可以看到平均值显示的是 6 位小数,没有货币符号,整数部分也没有千分号。此时,可以用 DataFrame 的 style.format 修饰。

代码如下,汇总计算的代码与上面相同,但多了 .style.format('${0:,.2f}'),引号里的 $ 符号代表美元,冒号(:)后的逗号代表千分号,.2f 代表 2 位小数。

(
   df.groupby(
'姓名')['金额']
   .agg([
'mean', 'sum'])
   .style.format(
'${0:,.2f}')
)

调整以后,数据显示如下:



可以看到,用了 .style.format() 函数以后,DataFrame 中平均值(mean)列显示的数据变成了带美元符号标记、整数部分带千分号、小数仅保留两位的样式,这种样式更便于理解金额这一概念。

如果只想保留整数,可使用 .style.format('${0:,.0f}'),把上面代码里的 2 改为 0,即可。

(
   df.groupby(
'姓名')['金额']
   .agg([
'mean', 'sum'])
   .style.format(
'${0:,.0f}')
)


货币样式示例2


此时,可以看到,货币数据已经按四舍五入的原则保留了整数。

如需了解更多 Python 字符串格式化示例,请参照 Python String Format Cookbook 

1.2 设定日期与百分比样式

接下来用 groupby 函数,按销售日期计算每月销售金额及其占年度销售总额的比例。

monthly_sales = df.groupby([pd.Grouper(key='日期', freq='M')])['金额'].agg(['sum']).reset_index()
monthly_sales[
'月占比'] = monthly_sales['sum']/df['金额'].sum()


日期与百分比示例1

此处可以看到,日期显示的是每个月的最后一天,比例一列则显示为 6 位小数,这种样式显然非常不直观,但一列一列调整样式也不是好方法,能不能一次性调整多列数据的样式呢?答案自然是,能!用样式字典就可以了。

format_dict = {'sum': '${0:,.0f}', '日期': '{:%Y-%m}', '月占比': '{:.2%}'}
monthly_sales.style.format(format_dict).hide_index()

上面的代码,首先把 format_dict 定义为一个样式字典,分别设置了汇总金额(sum)日期月占比三列的样式。其中,汇总金额为带美元符号、千分号、0 位小数的数字;日期为经典的“年月”格式,月占比则为带 2 位小数的百分比形式。

第二行代码,使用 style.format() 调用了第一行代码设定的样式字典(format_dict ),并用 hide_index() 隐藏了索引,隐藏索引的功能在很多情况下都有用,大家可以试试。


日期与百分比示例2

这样一来,DataFrame 的数据显示就变得比较可耐了,是不是数据显示得更清晰了,而且实现起来其实也很简单。

2. 突出显示最大值与最小值

Pandas 还支持用颜色突出显示符合条件的数据,类似 Excel 里的条件格式,本文主要演示一下如何突出显示某列数据里的最大值(浅绿色)与最小值(红色)。

(
   monthly_sales
   .style
   .format(format_dict)
   .hide_index()
   .highlight_max(color=
'lightgreen')
   .highlight_min(color=
'red')
)


突出显示最大值与最小值

这里的 color 参数除了可以用lightgreen 这样的关键词以外,还可以使用 '#cd4f39' 这样的颜色代码,更灵活。而且可以设置多个条件,比如可以同时设置 highlight_maxhighlight_min

3. 渐变色样式

只改变数字的样式,还不够,我们还想要更多,还想用颜色的深浅渐变来表示某一列数据占比的多少,其实这也是 Excel 已经提供了的功能,Pandas 也支持了。实现这一目标,需要使用 style 的 background_gradient 函数。

(
monthly_sales.style
.format(format_dict)
.background_gradient(subset=['sum'], cmap='BuGn')
)

上述代码设定了颜色渐变针对的列,subset=['sum'],色图用的是 cmap 参数,值为'BuGn',是一种绿色的渐变色图,色图的值请参阅 matplotlib 的文档 ,还有更多色彩可选。

显示效果如下,是不是觉得更直观了?


渐变色样式

4. 迷你条形图样式

除了渐变色,Pandas 还支持在 DataFrame 单元格里显示迷你条形图。

(
   monthly_sales
   .style
   .format(format_dict)
   .hide_index()
   .bar(color=
'#FFA07A', vmin=100_000, subset=['sum'], align='zero')
   .bar(color=
'lightblue', vmin=0, subset=['月占比'], align='zero')
   .set_caption(
'2018年销售一览表')
)

这里使用的是 style 的 bar 函数,分别需要设置几个参数,color 还是支持颜色编码与关键词,vmin 是基准值,比如销售额的基准值是 10 万,百分比的基准值是 1,subset 是针对的列,align 则代表对齐方式。

此外,还可以用 set_caption 函数设置 DataFrame 的标题。代码执行后,显示效果如下。


迷你条形图样式

5. Sparklines - 走势图

走势图这种样式不是 Pandas 的内置样式,但依然很实用,也很酷,它是一个叫 sparklines 的支持库提供的。详情请参阅它的文档 ,这个模块可以为 Pandas 的 DataFrame 添加迷你走势图。

首先,导入 sparklines

import sparklines

接着,定义调用 sparklines 的函数;

def sparkline_str(x):
   bins=np.histogram(x)[
0]
   sl =
' '.join(sparklines(bins))    return sl

sparkline_str.__name__ =
'走势图'

最后,在 groupby 函数里调用定义的 sparkline_str 函数;

df.groupby('姓名')['数量', '金额'].agg(['mean', sparkline_str])


迷你走势图示例

这种汇总功能可以很直观的显示数据,更有趣的是这个走势图是由纯文本组成的,又简单,又实用,对不?

总结

Pandas 的样式功能备受欢迎,尤其是分析师完成数据分析工作后,要给别人展示数据分析结果的时候,这个功能可以让你的数据分析报告更直观,更清晰。除了本文介绍的功能之外,其实还有更多样式与函数功能供你选择,本文只是引导您上手 Pandas 样式的基础入门,想要玩的更花俏,请自行研究 Pandas 官方的样式文档

最后,感谢 Alexas_Fotos 提供的图片,非常有创意。



翻译不易,四处求证、三天翻译、两天校对,只求一秒点赞 ,即右下方的 “在看”^_^

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多