(點選上方公眾號,可快速關註)
英文:Chris Moffitt ,編譯:伯樂線上/李加慶
簡介
在 Python 中,將資料視覺化有多種選擇,正是因為這種多樣性,何時選用何種方案才變得極具挑戰性。本文包含了一些較為流行的工具以及如何使用它們來建立簡單的條形圖,我將使用下麵幾種工具來完成繪圖示例:
-
Pandas
-
Seaborn
-
ggplot
-
Bokeh
-
pygal
-
Plotly
在示例中,我將使用 pandas 處理資料並將資料視覺化。大多數案例中,使用上述工具時無需結合 pandas,但我認為 pandas 與視覺化工具結合是非常普遍的現象,所以以這種方式開啟本文是很棒的。
什麼是 Matplotlib?
Matplotlib 是眾多 Python 視覺化包的鼻祖。其功能非常強大,同時也非常複雜。你可以使用 Matplotlib 去做任何你想做的事情,但是想要搞明白卻並非易事。我不打算展示原生的 Matplotlib 例子,因為很多工具(特別是 Pandas 和 Seaborn)是基於 Matplotlib 的輕量級封裝,如果你想瞭解更多關於 Matplotlib 的東西,在我的這篇文章— 《simple graphing》中有幾個例子可供參考(http://pbpython.com/simple-graphing-pandas.html)。
Matplotlib 令我最不滿的地方是它花費太多工作來獲得目視合理的圖表,但是在本文的某些示例中,我發現無需太多程式碼就可以輕鬆獲得漂亮的視覺化圖表。關於 Matplotlib 冗長特點的示例,可以參考這篇文章《ggplot》中的平面圖示例(http://blog.yhat.com/posts/ggplot-for-python.html)。
方法論
簡要說一下本文的方法論。我堅信只要讀者開始閱讀本文,他們將會指出使用這些工具的更好方法。我的標的並非在每個例子中創造出完全相同的圖表,而是花費大致相同的時間探索方法,從而在每個例子中以大體相同的方法將資料視覺化。
在這個過程中,我所面臨的最大挑戰是格式化 x 軸和 y 軸以及基於某些大的標簽讓資料看起來合理,弄明白每種工具是如何格式化資料的也花費了我不少精力,我搞懂這些之後,剩餘的部分就相對簡單了。
另外還需要註意的一點是,條形圖可能是製作起來相對更簡單的圖表,使用這些工具可以製作出多種型別的圖表,但是我的示例更加側重的是簡易的格式化,而不是創新式的視覺化。另外,由於標簽眾多,導致一些圖表佔據了很多空間,所以我就擅自移除了它們,以保證文章長度可控。最後,我又調整了圖片尺寸,所以圖片的任何模糊現象都是縮放導致的問題,並不代表真實影象的質量。
最後一點,我以一種嘗試使用 Excel 另外一款替代品的心態來實現示例。我認為我的示例在報告、展示、郵件或者靜態網頁中都更具說服力。如果你正在評估用於實時視覺化資料的工具,亦或是透過其他途徑去分享,那麼其中的部分工具會提供很多我還未涉獵到的功能。
資料集
之前的文章(http://pbpython.com/web-scraping-mn-budget.html)描述了我們要處理的資料,我從每一類中抽取了更深一層的樣例,並選用了更詳細的元素。這份資料集包含了125行,但是為了保持簡潔,我只選用了前10行,完整的資料集可以在這裡(http://pbpython.com/extras/mn-budget-detail-2014.csv)找到。
Pandas
我打算先使用 pandas DataFrame來繪圖。幸運地是,pandas 確實提供了內建的繪圖功能,此功能是基於 matplotlib,接下來我將以它作為開始。
首先,匯入模組並將資料讀入 budget DataFrame,將資料排序並取前10條。
import pandas as pd
budget = pd.read_csv(“mn-budget-detail-2014.csv”)
budget = budget.sort(‘amount’,ascending=False)[:10]
我們將在所有示例中使用相同的 budget 資料,下麵是其中5條:
現在,調整展示風格為更美觀的預設設定,並建立圖表:
pd.options.display.mpl_style = ‘default’
budget_plot = budget.plot(kind=“bar”,x=budget[“detail”],
title=“MN Capital Budget – 2014”,
legend=False)
上述程式碼使用 detail 列的資料完成了建立圖表的主要工作,同時展示了 title並移除了 legend 。
下麵是將圖表存為 png 格式的程式碼:
fig = budget_plot.get_figure()
fig.savefig(“2014-mn-capital-budget.png”)
圖表如下圖所示(截取了部分以使文章長度可控):
基礎圖表看起來不錯,理想情況下,我想對 y 軸再做一些格式化,但是這樣做需要使用 matplotlib 的一些功能。雖然現在的圖表已是完美可用的視覺化圖表了,但是僅僅透過 pandas 是不可能完成更多定製的。
Seaborn
Seaborn 是一個基於 matplotlib 的視覺化庫。它旨在使預設的資料視覺化更加悅目。它還旨在簡化複雜圖表的建立,可以與 pandas 很好地整合。
本例中並未明顯將 seaborn 區別於其他其他工具(譯者註:並未展示一些 seaborn 獨有或者特色的功能),我非常喜歡 seaborn 多樣的內建風格,可以快速地修改調色盤以使圖表看起來更美觀。其他方面,在建立這個簡易圖表時,並未使用 seaborn 做太多工作。
標準導包及讀取資料:
sns.set_style(“darkgrid”)
bar_plot = sns.barplot(x=budget[“detail”],y=budget[“amount”],
palette=“muted”,
x_order=budget[“detail”].tolist())
plt.xticks(rotation=90)
plt.show()
正如你所看到的,我必修使用 matplotlib 旋轉 x 軸的標題以便可以正常地閱讀。從外觀上看,圖表看起來不錯。理想情況下,我想格式化 y 軸上的刻度,但我不知道在不使用 matplotlib 中的 plt.yticks 的情況下,如何實現格式化。
ggplot
ggplot 與 Seaborn 類似,也是基於 matplotlib 並旨在以簡單的方式提高 matplotlib 視覺化的視覺感染力。它不同於 seaborn 是因為它是 ggplot2 為 R 語言準備的一個埠。基於這個標的,一些 API 的介面雖然不是很 pythonic 但是功能很強大。
我之前沒有在 R 中使用過 ggplot,所以可能有一個學習曲線,但是我可以感受到 ggplot 的吸引力。該庫正在積極發展,我也希望它可以繼續成長、成熟。我認為它會是一個非常強大的工具。學習過程中,我也曾多次努力去弄清楚如何實現一些功能,在查閱程式碼併在 Google 搜尋之後,我基本上搞明白了大部分。
繼續導包並讀取資料:
import pandas as pd
from ggplot import *
budget = pd.read_csv(“mn-budget-detail-2014.csv”)
budget = budget.sort(‘amount’,ascending=False)[:10]
現在讓我們透過連線幾條 ggplot 命令來構造圖表:
p = ggplot(budget, aes(x=“detail”,y=“amount”)) +
geom_bar(stat=“bar”, labels=budget[“detail”].tolist()) +
ggtitle(“MN Capital Budget – 2014”) +
xlab(“Spending Detail”) +
ylab(“Amount”) + scale_y_continuous(labels=‘millions’) +
theme(axis_text_x=element_text(angle=90))
print p
這似乎看起來有些奇怪 – 尤其是使用 print p 來顯示圖表。但是,我發現這樣相對簡單明瞭。
要弄清楚如何將文字旋轉 90 度以及如何將 x 軸上的標簽排序,確實要做些深入的挖掘。
我發現最酷的功能是 scale_y_continous, 它可以使標簽更美觀。
如果你想將圖表儲存為圖片,使用 ggsave可以很輕鬆地辦到:
ggsave(p, “mn-budget-capital-ggplot.png”)
下圖是最終的圖片,我知道灰色可能有點多,但是毫不費時就可以給它添些色彩。
Bokeh
Bokeh 不同於之前的3個庫,它不依賴於 matplotlib 並且實現的是面向現代瀏覽器的視覺化。它的標的是實現互動式的 web 視覺化,所以我的例子非常簡單。
導包並讀入資料:
import pandas as pd
from bokeh.charts import Bar
budget = pd.read_csv(“mn-budget-detail-2014.csv”)
budget = budget.sort(‘amount’,ascending=False)[:10]
bokeh 不同的一方面是我需要明確列出我繪圖需要的值。
details = budget[“detail”].values.tolist()
amount = list(budget[“amount”].astype(float).values)
現在我們可以繪圖了。下麵的程式碼將會實現在瀏覽器中展示包含圖表的 HTML 頁面,如果想用作其他展示,可以儲存其 png 格式的副本。
bar = Bar(amount, details, filename=“bar.html”)
bar.title(“MN Capital Budget – 2014”).xlabel(“Detail”).ylabel(“Amount”)
bar.show()
下麵是 png 格式的圖片:
正如你所看到的,圖表是非常乾凈的。我沒有找到一種更簡單的方式來格式化 y 軸。Bokeh 有很多功能,但在本例中我並未深入探索。
Pygal
Pygal 用於建立 svg 格式的圖表,如果安裝了正確的依賴,也可以儲存為 png 格式。svg 檔案在建立互動式圖表時非常有用,同時我也發現,使用此工具可以非常容易地建立獨特而又極具視覺感染力的圖表。
導包及讀取資料:
import pandas as pd
import pygal
from pygal.style import LightStyle
budget = pd.read_csv(“mn-budget-detail-2014.csv”)
budget = budget.sort(‘amount’,ascending=False)[:10]
我們需要建立圖表型別並做一些基礎設定:
bar_chart = pygal.Bar(style=LightStyle, width=800, height=600,
legend_at_bottom=True, human_readable=True,
title=‘MN Capital Budget – 2014’)
有趣的一點是 human_readable ,它可以很好地格式化資料,所以大多數情況下,這個功能“很管用”。
現在我們需要向圖表中新增資料,這是與 pandas 整合地不是很緊湊的地方,但是就本次的小資料集來說,可以直接新增資料。資料量很大時,效能可能會是一個問題。
for index, row in budget.iterrows():
bar_chart.add(row[“detail”], row[“amount”])
接下來,將檔案渲染為 svg 和 png 格式:
bar_chart.render_to_file(‘budget.svg’)
bar_chart.render_to_png(‘budget.png’)
我覺得 svg 的展示效果確實很好,我很喜歡看起來獨特且賞心悅目的風格。同時我也發現,我們可以相對容易地弄清楚使用此工具時,哪些可以實現,哪些不能實現。我鼓勵大家下載 svg 檔案,併在瀏覽器中感受圖表的互動效果。
Plot.ly
Plot.ly 區別於其他工具,是分析和視覺化的線上工具。它具有強大的 API 並包含一個 Python 版本。基於 Plot.ly,瀏覽網站時,你會看到豐富的互動式圖表。得益於優秀的檔案,建立條形圖會相對簡單。
你需要參考檔案設定 API 秘鑰,一旦設定完成,看起來所有工作就可以無縫對接了。需要警告的一點是,所有透過 Plot.ly 所做的東西都會釋出到網上,所有請確保你可以接受這一點,當然你也可以圖表設為私有。
Plotly 與 pandas 可以無縫整合。在這裡我也要對他們的認真負責並及時地回覆我的問題深表感謝。
導包並讀取資料:
import plotly.plotly as py
import pandas as pd
from plotly.graph_objs import *
budget=pd.read_csv(“mn-budget-detail-2014.csv”)
budget.sort(‘amount’,ascending=False,inplace=True)
budget = budget[:10]
為 plotly 設定資料及圖示型別:
data = Data([
Bar(
x=budget[“detail”],
y=budget[“amount”]
)
])
我決定再新增些額外的佈局資訊:
layout = Layout(
title=‘2014 MN Capital Budget’,
font=Font(
family=‘Raleway, sans-serif’
),
showlegend=False,
xaxis=XAxis(
tickangle=-45
),
bargap=0.05
)
最後,繪製資料。這將會開啟瀏覽器,並展示繪製好的圖示。起初我並未註意到,但是你可以使用 py.image.save_as,來儲存一個本地的副本,這是一個非常酷的功能。你可以得到基於網路的豐富的互動式報告以及用於巢狀在檔案中的本地圖表副本。
fig = Figure(data=data, layout=layout)
plot_url = py.plot(data,filename=‘MN Capital Budget – 2014’)
py.image.save_as(fig, ‘mn-14-budget.png’)
也可以檢視完整版本(https://plot.ly/~chris1610/12/),你可以在他們的網站上看到很多強大的例子。
Plot.ly 繪製出的圖表非常吸引人並且具有高度互動性。由於其優秀的檔案和 Python API 以及入門和執行都很簡單,所以我最喜歡 Plot.ly 這款產品。
總結
在 Python 生態系統中繪製資料是一件好事也是一件壞事。繪製資料的工具有很多可供選擇既是一件好事也是一件壞事,儘力搞清楚哪一個工具適合你取決於你要實現什麼。在一定程度上,你需要嘗試各種工具老弄清哪種工具適合你,我覺得沒有哪一個工具是最好或最壞。
下麵是我的一些見解:
-
Pandas 對於簡單的圖表繪製時非常方便的,但是你需要學習 matplotlib 來實現定製。
-
Seaborn 可以支援一些更複雜的視覺化方法,但仍需要 matplotlib 的知識來調整。顏色方案是一個不錯的功能。
-
ggplot 很有前景,但它仍在努力成長中。
-
如果你想建立自己的視覺化伺服器,bokeh 將是一個強大的工具。但是對於一些簡單的指令碼,使用 bokeh 就像殺雞用牛刀一樣。
-
pygal 在建立互動使 SVG 圖表和 PNG 檔案方面是獨一無二的。它不如基於matplotlib 的解決方案靈活。
-
Plotly 可以建立最具互動性的圖表。你可以離線儲存,並建立非常豐富的基於網路的視覺化圖表。
目前的情況是,我將持續關註 ggplot 的發展,併在需要互動性的地方使用pygal 和 plotly。
歡迎在評論中提供反饋。我相信,大家有很多關於這一主題的問題和意見。如果我錯過了什麼或者有其他的選擇,請告訴我。
看完本文有收穫?請轉發分享給更多人
關註「資料分析與開發」,提升資料技能