本文最初發布于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