本文最初发布于Anaconda开发者博客,经原作者授权由InfoQ中文站翻译并分享。
在奥斯汀举行的SciPy 2018年特别会议上,大量开源Python可视化工具的代表分享了他们对Python数据可视化未来的展望。我们看到了Matplotlib、Plotly、VisPy等许多库的更新。我作为PyViz、GeoViews、Datashader、Panel、hvPlot和Bokeh的代表参加了SciPy 2018大会,我在Anaconda的同事Jean-Luc Stevens则代表HoloViews参加。本文介绍了当前可用的软件包以及它们之间的关系。
当前生态
作为背景介绍,我先展示Jake VanderPlas的概览图,其中有许多不同而又相互关联的Python可视化库:
从中可以看到,这些库主要可以分成几组,每个组都有不同的起源、历史和关注点。显然,可视化物理位置数据的“SciVis”库(在图左下方)可以单独分成一组。这些工具(VisPy、glumpy、GR、Mayavi、ParaView、VTK和yt)主要是基于1992年OpenGL图形标准构建的,为规则或不规则网格数据提供了三维或四维(3D加上时间维度)物理过程图形密集可视化。这些库对富Web应用程序的支持早于HTML5,通常侧重于工程或科学环境中的高性能桌面GUI应用程序。
其他库几乎都属于“InfoVis”组,侧重于空间的信息可视化,而不一定是三维的物理世界。InfoVis库使用打印页面或计算机屏幕的两个维度来解释抽象空间,通常使用轴和标签。InfoVis库可以进一步细分为许多子组。
Matplotlib
2003年发布的最古老也最受流行的InfoVis库之一,具有非常广泛的2D绘图类型和输出格式。Matplotlib对富Web应用程序的支持也早于HTML5,而其侧重点放在了静态图像和使用桌面GUI工具包(如Qt和GTK)的交互式图形上。Matplotlib提供了一些3D支持,但比SciVis库提供的支持要有限得多。
基于Matplotlib的库
多年来,许多工具都是基于Matplotlib的2D绘图功能构建的,要么将它作为某类数据或某一领域(pandas、NetworkX、Cartopy、yt等)的渲染引擎,要么提供一个更高级的API来简化图形绘制(ggplot、plotnine、HoloViews、GeoViews等),要么添加了额外的图形类型(seaborn等)。
JavaScript
在HTML5为浏览器带来丰富的交互性之后,许多库就开始为网页和Jupyter Notebook提供交互式2D绘图,要么使用定制的JS(Bokeh、Toyplot) ,要么像D3一样以封装现有的JS库为主(Plotly、bqplot)。通过封装现有的JS库,很容易在巨大的JS市场引入新的图形,而使用自定义JS则允许定义较底层的JS原语,这些原语可以在Python中组合成全新的图形类型(如Bokeh)。
JSON
随着D3这样的JavaScript库日趋成熟,它们的功能已经被纳入声明性JSON规范(Vega、Vega-Lite),使得适用任何语言生成JavaScript图形变得更简单,现在也包括了Python(通过Altair,之前是通过vincent)。具有可移植JSON形式的完整绘图规范允许跨多种工具进行集成。
WebGL
就像HTML5对JavaScript 2D绘图所做的那样,WebGL标准为浏览器3D交互和Jupyter带来了可能性,这导致了基于three.js(pythreejs、ipyvolume) 、vtk.js(itk-jupyter-widgets) 或regl (Plotly)的浏览器3D绘图。这些新的基于Web的3D方法没有一种能够达到桌面库SciVis 3D的广度和深度,但是,它们确实可以与Jupyter Notebook完全集成,并且可以通过Web进行共享和远程使用。因此,尽管WebGL工具与SciVis工具有一些共同的应用,但它们与其他InfoVis工具的关系更为紧密。
其他
还有其他很多库,尽管没有出现在Jake的图中,但它们确实提供了其他补充功能(例如graphviz用于可视化网络)。
不同可视化工具的差异化特质
以上基于历史和技术的分类有助于解释我们当前为什么有大量Python可视化程序包,同时,它也有助于解释为什么不同包之间在用户功能方面存在着如此大的差异。具体来说,它们的主要差别在于支持的绘图类型、数据规模、用户界面和API类型,因此在选择库时不能只是出于个人喜好或便利性,而是需要考虑到以下一些因素。
绘图类型
最基本的绘图类型许多库都有,但其他的绘图类型只有某些库会提供。考虑到库的数量、绘图类型及它们在随时间变化,很难精确地描述每个库都支持什么。但是,如果你看一下每个库的示例,通常就可以弄清楚它们各自的侧重点是什么。下面是一个粗略的指南:
- 统计绘图(散点图、线、区域、条形图、直方图):几乎所有的InfoVis库都可以很好地覆盖这些图形,但Seaborn、bqplot、Altair、ggplot2、plotnine会比较侧重这些;
- 图像、规则网格、矩形网格:Bokeh、Datashader、HoloViews、Matplotlib、Plotly及大多数SciVis库都提供了很好的支持;
- 不规格2D网格(三角网格):SciVis库以及Matplotlib、Bokeh、Datashader、HoloViews提供了很好的支持;
- 地理数据:Matplotlib(和Cartopy一起)、GeoViews、ipyleaflet、Plotly;
- 网络/图:NetworkX、Plotly、Bokeh、HoloViews、Datashader;
- 3D(网格、散点等):SciVis库完全支持,Plotly、Matplotlib、HoloViews和ipyvolume部分支持。
数据规模
每个库的架构和底层技术决定了它们所支持的数据规模,这样就可以知道该库是否适用于大图片、电影、多维数组、长时间序列、网格或其他大型数据集:
- SciVis:通常可以处理非常大的网格数据集,GB级别或更大,它使用编译过的“数据库(data libraries)”和原生GUI应用程序;
- 基于Matplotlib:通常可以处理几十万个点,并提供合理的性能,在某些特殊情况下可以处理更多的点;
- JSON:如果没有特殊处理,基于JSON文本的数据编码会将基于JSON的规范限制在几千个点到几十万个点之间,这取决于文件大小和所需的文本处理;
- JavaScript:ipywidgets、Bokeh和Plotly都使用JSON,但增加了额外的二进制数据传输机制,以便能够处理数十万到数百万个数据点;
- WebGL:为了获得良好的性能,使用HTML Canvas的JavaScript库限制在最多几十万个点,但是WebGL(通过ipyvolume、Plotly或Bokeh)最多支持数百万个点;
- 服务器端渲染:来自Datashader或Vaex的外部InfoVis服务器端渲染支持数十亿、数万亿或更多数据点进入Web浏览器,通过将任意大小的分布式数据集或非核心数据集转换为固定大小的图像嵌入到客户端浏览器中。
由于这些类型的库所支持的数据规模(在某种程度上可以说是数据类型)范围很大,因此,需要使用大型数据集的用户首先需要选择合适的库。
用户界面和发布
各种类型的库在图形的使用方式方面存在巨大差异。
- 静态图像:大多数库现在支持通过“headless”的方式来创建静态图像,至少对于PNG和平滑矢量格式(如SVG或PDF)来说是这样的。
- 原生GUI应用程序:SciVis库加上Matplotlib和Vaex可以创建特定于操作系统的GUI窗口,这些窗口提供了很高的性能,支持大型数据集,并与其他桌面应用程序集成。但是,它们与特定的操作系统绑定在一起,通常需要在本地运行,而不是在Web上。在某些情况下,基于JavaScript的工具也可以通过嵌入Web浏览器嵌入到本地应用程序中。
- 导出到HTML:大多数JavaScript和JSON库都可以在无服务器模式下运行,生成交互式图形(缩放、平移等),可以通过电子邮件或在Web服务器上发布,而不需要依赖Python。
- Jupyter Notebook:大多数InfoVis库现在都支持Jupyter Notebook交互式应用,借助Python提供的基于JavaScript的绘图。基于ipywidgets的项目提供了与Jupyter更紧密的集成,而其他一些方法只提供了有限的Jupyter交互性。
- 基于Web的仪表盘和应用程序:借助Dash,Plotly图形可以用于单独部署的应用程序,Bokeh、HoloViews和GeoViews可以使用Bokeh服务器部署。大多数其他InfoVis库可以使用新的Panel库部署成仪表盘,比如Matplotlib、Altair、Plotly、Datashader、hvPlot、Seaborn、plotnine和yt。然而,尽管它们提供了基于Web的交互性,但基于ipywidgets的库(ipyleaflet、pythreejs、ipyvolume、bqplot)很难部署成面向公众的应用程序,因为Jupyter协议允许执行任意代码(请参考Jupyter仪表盘和flask-ipywidgets,它们或许可以作为潜在的解决方案)。
因此,用户需要考虑给定的库是否涵盖了他们对可视化的预期使用范围。
API类型
各种InfoVis库提供了大量的编程接口,适用于各种差别很大的用户,并提供了不同创建可视化的方式。在执行普通任务所需的代码量、为用户处理不常见任务提供多大的控制自由度以及将原语组合成新类型图形方面,这些API存在巨大的差别。
- 面向对象的Matplotlib API:Matplotlib的主要API,允许完全控制和组合,但对于一些常见的任务,如创建子图,则非常复杂和繁琐。
- 命令式Pyplot API:Matplotlib的基本接口,允许使用Matplotlib风格的命令式命令,对于比较简单的情况,这些命令很简洁,但不可组合。因此,它们在很大程度上仅限于一组特定的支持选项。
- 命令式Pandas .plot() API:以dataframe为中心,用户将主要通过Pandas来准备数据,然后选择一个子集进行绘图。它们现在支持各种图形库及其他数据结构。不是直接组合,但可以从底层绘图库(如hvPlot)返回可组合的对象。
- 声明式图形API:受“图形语法( Grammar of Graphics)”启发的库(如ggplot、plotnine、Altair)和Bokeh提供了一种自然的方式来组合图形原语(如坐标轴和符号),用来创建完整的图形。
- 声明式数据API:构建在其他库的原生API的基础上,HoloViews和GeoViews提供了一个更高级的声明式复合API,主要关注注解、描述和使用可视化数据,而不是绘图元素。
这些API都适用于具有不同背景和目标的用户,这使得处理一些任务变得更简单,而另一些任务则变得更加困难。除了Matplotlib之外,大多数库都支持一种或至多两种备选API。因此,选择一个符合每个用户技术背景和首选工作流的库显得非常重要。
最新趋势
如你所见,Python有大量的可视化功能库,大量可用的库反映出了方法和侧重点的多样性。方法之间的差异仍然很重要,并且具有深远的影响,这意味着用户在特定的方法上大幅投入之前需要考虑这些差异。但是,正如我们在SciPy 2018上看到的那样,趋同趋势降低了用户选择的关键性。
查看英文原文:https://www.anaconda.com/blog/developer-blog/python-data-visualization-2018-why-so-many-libraries