作者:Dan Saber
翻译:笪洁琼
校对:梁傅淇
本文约16196字,建议阅读20+分钟。
本文中,作者借助拟人化的形式,让Python中值得一提的可视化库共同出演了一出戏剧,形象、生动地展现了不同可视化库的特点。
本文最初发表于丹·萨伯的博客(https://dsaber.com/2016/10/02/a-dramatic-tour-through-pythons-data-visualization-landscape-including-ggplot-and-altair/)我们觉得很有意思,所以问他是否可以转载,他慷慨地答应了!
关于丹:我叫丹·萨伯。我毕业于加州大学洛杉矶分校的数学系,我在Coursera上从事数据科学工作(在此之前,我在金融行业工作)。我喜欢写作、音乐、编程,还有——经过美国教育系统的最佳培训——统计。
为什么还要去尝试,朋友们?
最近,我尝试了Brian Granger和 Jake VanderPlas开发的Altair,这是一个新的、很有前景的可视化库。Altair库似乎能够满足Python用户对于ggplot库的需求,而且它建立在JavaScript的Vega-Lite语法规范之上,随着后者开发新的功能(例如:工具提示和缩放),Altair也能受益——而且毫不费力!
事实上,我对Altair库印象是如此深刻以至于这篇文章最初的主题是:“哟,用Altair吧!”
然后我开始反思自己使用Python来进行可视化的编码习惯,经过痛苦的自我反省,之后,我意识到我自己总是以任务为标准来采用一堆杂七杂八的工具和杂乱的技术之中(通常是我第一次用来完成这个任务的库) 。
这并不好。就像老话说的那样:“ 未经检验的图表不值得导出成PNG格式。”
因此,我将Altair库放到一个次要的位置——用以探索Python的统计可视化工具是如何结合在一起的。我希望这次探索对你也有帮助。
接下来如何做?
这篇文章的构思将会是:“你要做事件X,你要如何使用matplotlib、Pandas库/ Seaborn库/ ggpy库/ Altair库做事件X?”在使用不同的工具做事件X的情况下,我们将列出一个合理的利弊列表,或者至少是一串可能有用的代码。
(警告:这一切都可能以两幕剧的形式出现。)
工具(按照主观感觉按复杂度降序排序)
首先,欢迎我们的朋友们:
Matplotlib库
http://matplotlib.org/
这只重达800磅的大猩猩,和大多数800磅重的大猩猩一样,除非你真的需要它的力量,比如说制作一个定制化的或可供出版的图表,否则我们应该避免使用它来。
(正如我们将看到的,当涉及到统计可视化时,首选的方法可能是:“使用舒适的工具,比如以下要谈到的四个工具轻松地做尽可能多的事情,然后用matplotlib做剩下的事情”。)
Pandas库
http://pandas.pydata.org/pandas-docs/stable/visualization.html
“为了数据框而来,为被比其所取代的matplotlib编码要令人愉悦的便利的可视化函数而留下。”。——未被采用的Pandas标语
(花边新闻:Pandas开发团队里面一定包括一些可视化迷,因为这个库中包含了像RadViz图还有Andrews曲线这样我在其他地方都没有看到过的东西。)
Seaborn库
http://seaborn.pydata.org/
Seaborn库长期以来一直是我常用的数据可视化库;它自我总结道:
“如果matplotlib’试图让简单的事情变得更加容易,困难的事情变得可能’,那么Seaborn库则是试图将一套明确定义的复杂的东西也变得简单起来。”
yhat的ggpy库
https://github.com/yhat/ggpy
非常棒的声明式ggplot2库在Python中的实现,这并非一个“ggplot2的特性一对一移植”,而是在原功能的基础上有很强的增强。
(作为一名偶尔使用R的用户,我认为主要的geoms功能基本都实现了。)
Altair库
https://github.com/ellisonbg/altair
一个新东西,Altair是一个带有使用体验令人非常棒的应用程序接口的“声明式统计可视化库”。
太棒了。现在我们的客人已经抵达并且放好了他们的外套,让我们安稳地坐下来,开始我们的晚餐谈话吧。我们的节目已经开场了......
Python可视化库的小剧场(所有的库都出演它自己)
第一幕:线条和圆点
(在场景1中,我们将处理一个名为ts的“整洁”数据集。它由三列组成:一个dt列(date:日期);value列(值);还有一个kind列,它有四个不同的水平:A、B、C和D,数据集长这个样子:)
dt |
kind |
value |
|
0 |
2000-01-01 |
A |
1.442521 |
1 |
2000-01-02 |
A |
1.981290 |
2 |
2000-01-03 |
A |
1.586494 |
3 |
2000-01-04 |
A |
1.378969 |
4 |
2000-01-05 |
A |
-0.277937 |
场景1:你如何在同一张图上绘制多个时间序列?
Matplotlib(MPL):哈!哈哈!简直不能更简单了。虽然我可以用许多复杂的方法来完成这项任务,但我知道,你们那脆弱的大脑会在他们精巧的重压下崩溃。因此,我将其简化,向你们展示两个简单的方法。在第一种方法中,我循环使用你们虚构的矩阵——我相信你们这些家伙把它叫做“数据”“框架”——并将其子集传递给相关的时间序列。接下来,我调用plot方法,传入该子集中的相关列。
# MATPLOTLIB
fig, ax = plt.subplots(1, 1,
figsize=(7.5, 5))
for k in ts.kind.unique():
tmp = ts[ts.kind == k]
ax.plot(tmp.dt, tmp.value, label=k)
ax.set(xlabel='Date',
ylabel='Value',
title='Random Timeseries')
ax.legend(loc=2)
fig.autofmt_xdate()
MPL:接下来,我让这个大笨蛋(指了指Pandas)把这个“数据”的“框架”做轴向旋转,之后它就长这个样子......
# the notion of a tidy dataframe matters not here(Markdown 代码编辑部分)
dfp = ts.pivot(index='dt', columns='kind', values='value')
dfp.head()
kind |
A |
B |
C |
D |
dt |
||||
2000-01-01 |
1.442521 |
1.808741 |
0.437415 |
0.096980 |
2000-01-02 |
1.981290 |
2.277020 |
0.706127 |
-1.523108 |
2000-01-03 |
1.586494 |
3.474392 |
1.358063 |
-3.100735 |
2000-01-04 |
1.378969 |
2.906132 |