这篇文章是关于 Python 数据可视化工具现状及其在 SciPy 2018 中出现的趋势的三部分系列文章中的第一篇。
作者:James A. Bednar
在奥斯汀举行的 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 随时间变化)中可视化物理过程的图形密集型可视化,适用于规则或不规则网格数据。这些库早于 HTML5 对富 Web 应用程序的支持,通常侧重于工程或科学环境中的高性能桌面 GUI 应用程序。
其他库几乎都属于“InfoVis” 组,专注于可视化任意空间中的信息,不一定是指三维物理世界。InfoVis 库使用打印页面或计算机屏幕的二维空间来使抽象空间可解释,通常使用轴和标签。InfoVis 库可以进一步细分为许多子组。
Matplotlib
InfoVis 库中最古老且最受欢迎的库之一,于 2003 年发布,具有非常广泛的 2D 图表类型和输出格式。Matplotlib 也早于 HTML5 对富 Web 应用程序的支持,而是侧重于为出版物创建静态图像,以及使用 Qt 和 GTK 等桌面 GUI 工具包创建交互式图形。Matplotlib 包含一些 3D 支持,但比 SciVis 库提供的支持要有限得多。
基于 Matplotlib 的库
多年来,各种工具都在 Matplotlib 的 2D 绘图功能之上构建,无论是将其用作特定类型数据或特定领域的渲染引擎(pandas、NetworkX、Cartopy、yt 等),还是在它之上提供更高层的 API 来简化绘图创建(ggplot、plotnine、HoloViews、GeoViews),或者通过额外的图表类型对其进行扩展(seaborn 等)。
JavaScript
一旦 HTML5 允许在浏览器中进行丰富的交互,许多库便出现以提供用于网页和 Jupyter 笔记本的交互式 2D 图表,无论是使用自定义 JS(Bokeh、Toyplot),还是主要包装现有的 JS 库,如 D3(Plotly、bqplot)。包装现有的 JS 使得轻松添加为大型 JS 市场创建的新图表(如 Plotly),而使用自定义 JS 允许定义更低级的 JS 原语,这些原语可以在 Python 中组合成全新的图表类型(如 Bokeh)。
JSON
随着 D3 等 JavaScript 库的成熟,其功能已在声明式 JSON 规范中捕获(Vega、Vega-Lite),使得从任何语言(现在包括 Python,通过 Altair,以及之前通过 vincent)生成 JavaScript 图表变得轻而易举。拥有可移植 JSON 格式的完整图表规范允许在多种工具之间进行集成。
WebGL
正如 HTML5 对 2D JavaScript 绘图所做的那样,WebGL 标准使在浏览器和 Jupyter 中进行 3D 交互成为可能,从而导致了基于 three.js(pythreejs、ipyvolume)、vtk.js(itk-jupyter-widgets)或 regl(Plotly)的 3D 浏览器内绘图。这些较新的基于 Web 的 3D 方法都无法与桌面 SciVis 3D 库的广度和深度相媲美,但它们确实允许与 Jupyter 笔记本完全集成,并通过 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:通常可以使用编译后的数据库和原生 GUI 应用程序处理非常大的网格数据集,大小为千兆字节或更大。
基于 Matplotlib 的库:通常可以使用合理性能处理数十万个点,或者在某些特殊情况下处理更多点(例如,取决于后端)。
JSON:如果没有特殊处理,JSON 对数据的文本编码会将基于 JSON 的规范限制为 几千个点 到几十万个点,因为需要处理文件大小和文本。
JavaScript:ipywidgets、Bokeh 和 Plotly 都使用 JSON,但通过额外的二进制数据传输机制对其进行了扩展,因此可以处理数十万到数百万个数据点。
WebGL:使用 HTML Canvas 的 JavaScript 库在性能方面被限制为最多几十万个点,但 WebGL(通过 ipyvolume、Plotly,以及在某些情况下通过 Bokeh)允许处理到数百万个点。
服务器端渲染:来自 Datashader 或 Vaex 的外部 InfoVis 服务器端渲染允许在 Web 浏览器中处理数十亿、数万亿甚至更多的数据点,方法是将任意大的分布式或离核数据集转换为固定大小的图像以嵌入到客户端浏览器中。
由于这些类型库支持的数据大小(因此在某种程度上也支持数据类型)范围很广,因此需要处理大型数据集的用户需要在开始时选择合适的库。
用户界面和发布
各种库在图表的使用方式上存在很大差异。
静态图像:大多数库现在都可以以无头方式运行来创建静态图像,至少可以创建 PNG,并且通常可以创建平滑的矢量格式,如 SVG 或 PDF。
原生 GUI 应用程序:SciVis 库加上 Matplotlib 和 Vaex 可以创建特定于操作系统的 GUI 窗口,这些窗口提供高性能、对大型数据集的支持以及与其他桌面应用程序的集成,但与特定操作系统绑定,通常需要在本地运行而不是在网络上运行。在某些情况下,基于 JavaScript 的工具也可以通过嵌入网络浏览器嵌入到原生应用程序中。
导出到 HTML:大多数 JavaScript 和 JSON 库可以在无服务器模式下运行,生成交互式图表(缩放、平移等),这些图表可以在没有 Python 的情况下通过电子邮件发送或发布到 Web 服务器上。
Jupyter 笔记本:大多数 InfoVis 库现在支持在 Jupyter 笔记本中进行交互式使用,其中基于 JavaScript 的图表由 Python 支持。基于 ipywidgets 的项目提供了与 Jupyter 的更紧密集成,而其他一些方法在 Jupyter 中仅提供有限的交互性(例如,当与 Matplotlib 而不是 Bokeh 一起使用时,HoloViews)。
独立的基于 Web 的仪表盘和应用程序:Plotly 图表可以使用 Dash 在单独的可部署应用程序中使用,而 Bokeh、HoloViews 和 GeoViews 可以使用 Bokeh Server 部署。大多数其他 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 的基本接口 允许 Matlab 风格的命令式命令,这些命令对于简单情况来说很简洁,但不可组合,因此很大程度上局限于一组特定的支持选项。
命令式 Pandas .plot() API:以数据帧为中心,用户主要在 Pandas 中准备数据,然后选择一个子集进行绘图。正如下一篇文章中将讨论的那样,现在支持范围广泛的图表库以及其他数据结构,使它们成为一组有用的广泛支持的基本绘图命令。不能直接组合,但可以从底层绘图库返回可组合的对象(如 hvPlot)。
声明式图形 API:图形语法 启发的库(如 ggplot、plotnine、Altair 和(在某种程度上)Bokeh 提供了一种自然的方式来组合图形基元(如轴和字形)以创建一个完整的图形。
声明式数据 API:建立在其他库的原生 API 基础上,HoloViews 和 GeoViews 提供了一个更高层次的声明式和可组合 API,重点在于注释、描述和处理可视化数据,而不是图形元素。
每个 API 都适合具有不同背景和目标的用户,使某些任务变得容易和简洁,而另一些任务则更难。除了 Matplotlib 之外,大多数库都支持一个或最多两个替代 API,因此选择一个其方法适合每个用户的技术背景和首选工作流程的库非常重要。
新兴趋势
如您所见,Python 提供了大量可视化功能,方法和重点的多样性体现在大量可用库中。方法之间的差异仍然很重要,并具有深远的影响,这意味着用户需要在深入投资任何特定方法之前考虑这些差异。但正如我们在 *SciPy 2018* 中看到的那样,走向融合的趋势有助于减少用户选择哪些库的必要性。要详细了解这些新兴趋势,请关注本系列的 第二部分*Python 数据可视化 2018:走向融合*。