本文最初发布于 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
评论 1 条评论