【呆鸟译Py】浅谈 Pandas 样式

浅谈Pandas样式

Python大咖谈 - Kenneth Reitz 与 Mike Driscoll
Python大咖谈 - Brett Cannon(一)
Python大咖谈 - Brett Cannon(二)

简介

大家都知道 Excel 可以设定单元格格式,还支持单元格迷你图,其实 Pandas 也可以,本文参照 Chris MoffittStylin’ 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 年的销售数据,但汉化了数据表的标题,方便大家在代码中识别数据列的信息;

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

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

Jupyter Notebook 示例文件,点击下载

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}')
)

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

货币样式示例1

可以看到,用了 .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 也支持了。实现这一目标,需要使用 stylebackground_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年销售一览表')
)

这里使用的是 stylebar 函数,分别需要设置几个参数,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 提供的图片,非常有创意。

Python大咖谈 - Kenneth Reitz 与 Mike Driscoll
Python大咖谈 - Brett Cannon(一)
Python大咖谈 - Brett Cannon(二)

【呆鸟云】翻译不易,四处求证、三天翻译、两天校对,只求一秒点赞 _

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 218,122评论 6 505
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,070评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,491评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,636评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,676评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,541评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,292评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,211评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,655评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,846评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,965评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,684评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,295评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,894评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,012评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,126评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,914评论 2 355

推荐阅读更多精彩内容