教程 | 如何优雅而高效地使用Matplotlib实现数据可视化
本文經機器之心(微信公眾號:almosthuman2014)授權轉載,禁止二次轉載”
參與:路雪、蔣思源
Matplotlib?能創建非常多的可視化圖表,它也有一個豐富的?Python?工具生態環境,很多更高級的可視化工具使用?Matplotlib?作為基礎庫。因此本文旨在提供一種高效的?Matplotlib?使用方法,并希望該方法可以幫助大家理解如何更有效地進行日常數據分析工作。
簡介
對新手來說?Python?可視化實在有些令人挫敗。有很多不同的選項,如何選擇正確的選項是一個挑戰。例如,兩年前這篇文章《Overview?of?Python?Visualization?Tools》仍然吸引了大量讀者。在那篇文章中,我否定了?Matplotlib。但是,在使用過?pandas、scikit-learn、seaborn?和其他?Python?數據科學包之后,我覺得之前否認?Matplotlib?的行為有點不成熟。坦白講,當時我不是很了解?Matplotlib,也不懂如何在我的工作流中高效使用?Matplotlib。
現在我學習了一些工具,了解了如何基于?Matplotlib?使用這些工具,Matplotlib?逐漸變成了可視化工具的核心。本文將展示如何使用?Matplotlib。我堅定地認為?Matplotlib?是?Python?數據科學包必不可少的一部分,希望這篇文章可以幫助大家了解如何使用?Matplotlib?進行?Python?可視化。
為什么大家都在否定?Matplotlib?
我認為,Matplotlib?對于新手來說比較難存在幾個原因。首先,Matplotlib?有兩個界面。第一個界面基于?MATLAB,使用基于狀態的接口。第二個界面是面向對象的接口。本文就不展開介紹?Matplotlib?有兩個界面的原因,但了解這兩種方法在使用?Matplotlib?繪圖時會很重要。兩個界面會引起混淆的原因可以通過?Stack?Overflow?和谷歌搜索查找一些信息。此外,新用戶將發現混淆問題有多個解決方案,但是這些問題看起來類似卻不完全相同。從我的個人經驗來講,我們從以前的代碼中可以看出有一些?Matplotlib?代碼的混雜。
關鍵點
Matplotlib?新手應該學習和使用面向對象的接口。
使用?Matplotlib?的另一個歷史性挑戰是一些默認的樣式缺乏吸引力。在?R?使用?ggplot?就可以生成相當不錯的圖,而?Matplotlib?相對來說有點丑。好消息是?Matplotlib?2.0?中的樣式好看了很多,你可以用最小的努力生成可視化。
第三個挑戰是你不確定什么時候該使用?Matplotlib,什么時候該使用基于?Matplotlib?構建的工具,如?pandas?或?seaborn。大部分時候做一件事都有多種選擇,但是對于新手來說選擇正確的道路有些困難。
為什么使用?Matplotlib?
盡管?Matplotlib?有這么多問題,我還是喜歡用它。因為它很強大,這個庫允許你創建幾乎所有的可視化圖表。此外,圍繞?Matplotlib?有一個豐富的?Python?工具生態環境,很多更高級的可視化工具使用?Matplotlib?作為基礎庫。因此如果你想在?Python?數據科學工具包中進行任何操作,你需要對如何使用?Matplotlib?有一些基礎了解。這就是本文其余部分的重點,提供一種高效使用?Matplotlib?的基礎方法。
前提
推薦以下步驟學習如何使用?Matplotlib:
1.?學習?Matplotlib?的基本術語,具體來說就是什么是?Figure?和?Axes。
2.?一直使用面向對象的界面,養成習慣。
3.?用基礎的?pandas?繪圖開始可視化。
4.?使用?seaborn?進行稍微復雜的數據可視化。
5.?使用?Matplotlib?自定義?pandas?或?seaborn?可視化。
下圖非常重要,有助于理解圖的不同術語。
大部分術語很直接易懂,需要牢記的是?Figure?是可能包含一或多個?axes?的最終圖像。Axes?代表單個圖。一旦你理解這些是什么以及如何通過面向對象的?API?評估它們,其余步驟就很簡單了。
了解這個知識還有一個好處,就是當你在網絡上看東西的時候有一個出發點。如果你花時間了解了這個點,那么其他的?Matplotlib?API?才有意義。此外,很多高級?Python?包,如?seaborn?和?ggplot?依賴于?Matplotlib?構建,因此理解了基礎,學習更強大的框架才更加容易。
最后,我不是說你應該逃避其他優秀選項,如?ggplot(又名?ggpy)、bokeh、plotly?或?altair。我只是認為你需要對?matplotlib?+?pandas?+?seaborn?有一個基礎的了解。了解基礎可視化棧之后,你就可以探索其他優秀工具,根據需求做出合適的選擇。
開始
下面主要介紹如何在?pandas?中創建基礎的可視化以及使用?Matplotlib?定制最常用的項。了解基礎流程有助于更直觀地進行自定義。
我主要關注最常見的繪圖任務,如標注軸、調整圖形界限(limit)、更新圖標題、保存圖像和調整圖例。
開始,我打算設置輸入,讀取一些數據:
import pandas as pdimport matplotlib.pyplot as pltfrom matplotlib.ticker import FuncFormatter
df = pd.read_excel("https://github.com/chris1610/pbpython/blob/master/data/sample-salesv3.xlsx?raw=true")
df.head()
數據包括?2014?年的銷售交易額。為簡短起見,我將總結這些數據,列出前十名客戶的采購次數和交易額。繪圖時我將對各列進行重命名。
top_10 = (df.groupby('name')['ext price', 'quantity'].agg({'ext price': 'sum', 'quantity': 'count'})
? ? ? ? ?.sort_values(by='ext price', ascending=False))[:10].reset_index()
top_10.rename(columns={'name': 'Name', 'ext price': 'Sales', 'quantity': 'Purchases'}, inplace=True)
下圖是數據。
現在數據以簡單的表格形式呈現,我們再來看一下如何將數據繪制成條形圖。如前所述,Matplotlib?具備多種不同風格,可用于渲染圖表。你可以使用?plt.style.available?查看你的系統可用的風格。
plt.style.available
['seaborn-dark', 'seaborn-dark-palette', 'fivethirtyeight', 'seaborn-whitegrid', 'seaborn-darkgrid', 'seaborn', 'bmh', 'classic', 'seaborn-colorblind', 'seaborn-muted', 'seaborn-white', 'seaborn-talk', 'grayscale', 'dark_background', 'seaborn-deep', 'seaborn-bright', 'ggplot', 'seaborn-paper', 'seaborn-notebook', 'seaborn-poster', 'seaborn-ticks', 'seaborn-pastel']
使用如下簡單風格:
plt.style.use('ggplot')
現在我們有了好看的風格,第一步就是使用標準?pandas?繪圖函數繪制數據:
top_10.plot(kind='barh', y="Sales", x="Name")
推薦使用?pandas?繪圖的原因在于它是一種快速便捷地建立可視化原型的方式。
自定義圖表
如果你對該圖表的重要部分都很滿意,那么下一步就是對它執行自定義。一些自定義(如添加標題和標簽)可以使用?pandas?plot?函數輕松搞定。但是,你可能會發現自己需要在某個時刻跳出來。這就是我推薦你養成以下習慣的原因:
fig, ax = plt.subplots()
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
生成的圖表和原始圖表基本一樣,不過我們向?plt.subplots()?添加了一個額外的調用,并將?ax?傳輸至繪圖函數。因此,通過?ax?或?fig?對象可以執行任何自定義。
我們利用?pandas?實現快速繪圖,現在利用?Matplotlib?獲取所有功能。通過使用命名慣例,調整別人的解決方案適應自己的需求變得更加直接簡單了。
假設我們想調整一些軸標簽,且?ax?變量中有多個軸,可以進行一些操作:
fig, ax = plt.subplots()
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
ax.set_xlim([-10000, 140000])
ax.set_xlabel('Total Revenue')
ax.set_ylabel('Customer');
這是另一種改變標題和標簽的簡單方式:
fig, ax = plt.subplots()
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
ax.set_xlim([-10000, 140000])
ax.set(title='2014 Revenue', xlabel='Total Revenue', ylabel='Customer')
為了進一步展示該方法,我們還可以使用?plt.subplots()?函數可以定義圖像尺寸,一般以英寸為單位。我們還可以使用?ax.legend().set_visible(False)?移除圖例。
fig, ax = plt.subplots(figsize=(5, 6))
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
ax.set_xlim([-10000, 140000])
ax.set(title='2014 Revenue', xlabel='Total Revenue')
ax.legend().set_visible(False)
要想修改這個圖像,你可能需要執行很多操作。圖中最礙眼的可能是總收益額的格式。Matplotlib?可以使用?FuncFormatter?解決這一問題。該函數用途多樣,允許用戶定義的函數應用到值,并返回格式美觀的字符串。
以下是貨幣格式化函數,用于處理數十萬美元區間的數值:
def currency(x, pos):
? ?'The two args are the value and tick position'
? ?if x >= 1000000: ? ? ? ?return '${:1.1f}M'.format(x*1e-6) ? ?return '${:1.0f}K'.format(x*1e-3)
現在我們有了格式化程序函數,就需要定義它,并將其應用到?x?軸。完整代碼如下:
fig, ax = plt.subplots()
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
ax.set_xlim([-10000, 140000])
ax.set(title='2014 Revenue', xlabel='Total Revenue', ylabel='Customer')
formatter = FuncFormatter(currency)
ax.xaxis.set_major_formatter(formatter)
ax.legend().set_visible(False)
這張圖美觀多了,非常好地展示了自定義問題解決方案的靈活性。最后要說的自定義特征是向圖表添加注釋。你可以使用?ax.axvline()?畫垂直線,使用?ax.text()?添加自定義文本。就以上示例,我們可以畫一條表示平均值的線,包括代表?3?個新客戶的標簽。以下是完整代碼(包括注釋):
# Create the figure and the axes
fig, ax = plt.subplots()
# Plot the data and get the averaged
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
avg = top_10['Sales'].mean()
# Set limits and labels
ax.set_xlim([-10000, 140000])
ax.set(title='2014 Revenue', xlabel='Total Revenue', ylabel='Customer')
# Add a line for the average
ax.axvline(x=avg, color='b', label='Average', linestyle='--', linewidth=1)
# Annotate the new customers
for cust in [3, 5, 8]:
? ?ax.text(115000, cust, "New Customer")
# Format the currency
formatter = FuncFormatter(currency)
ax.xaxis.set_major_formatter(formatter)
# Hide the legend
ax.legend().set_visible(False)
圖表
目前,我們所做的所有改變都是針對單個圖表。我們還能夠在圖像上添加多個表,使用不同的選項保存整個圖像。
如果我們確定要在同一個圖像上放置兩個表,那么我們應該對如何做有一個基礎了解。首先,創建圖像,然后創建軸,再將它們繪制成圖表。使用?plt.subplots()?可以完成該操作:
fig, (ax0, ax1) = plt.subplots(nrows=1, ncols=2, sharey=True, figsize=(7, 4))
在這個例子中,我使用?nrows?和?ncols?指定大小,這對新用戶來說比較清晰易懂。我還使用?sharey=True?以使?y?軸共享相同的標簽。
該示例很靈活,因為不同的軸可以解壓成?ax0?和?ax1。現在我們有了這些軸,就可以像上述示例中那樣繪圖,然后把一個圖放在?ax0?上,另一個圖放在?ax1。
# Get the figure and the axes
fig, (ax0, ax1) = plt.subplots(nrows=1,ncols=2, sharey=True, figsize=(7, 4))
top_10.plot(kind='barh', y="Sales", x="Name", ax=ax0)
ax0.set_xlim([-10000, 140000])
ax0.set(title='Revenue', xlabel='Total Revenue', ylabel='Customers')
# Plot the average as a vertical line
avg = top_10['Sales'].mean()
ax0.axvline(x=avg, color='b', label='Average', linestyle='--', linewidth=1)
# Repeat for the unit plot
top_10.plot(kind='barh', y="Purchases", x="Name", ax=ax1)
avg = top_10['Purchases'].mean()
ax1.set(title='Units', xlabel='Total Units', ylabel='')
ax1.axvline(x=avg, color='b', label='Average', linestyle='--', linewidth=1)
# Title the figure
fig.suptitle('2014 Sales Analysis', fontsize=14, fontweight='bold');
# Hide the legends
ax1.legend().set_visible(False)
ax0.legend().set_visible(False)
現在,我已經在?jupyter?notebook?中用?%matplotlib?inline?展示了很多圖像。但是,在很多情況下你需要以特定格式保存圖像,將其和其他呈現方式整合在一起。
Matplotlib?支持多種不同文件保存格式。你可以使用?fig.canvas.get_supported_filetypes()?查看系統支持的文件格式:
fig.canvas.get_supported_filetypes()
{'eps': 'Encapsulated Postscript', 'jpeg': 'Joint Photographic Experts Group', 'jpg': 'Joint Photographic Experts Group', 'pdf': 'Portable Document Format', 'pgf': 'PGF code for LaTeX', 'png': 'Portable Network Graphics', 'ps': 'Postscript', 'raw': 'Raw RGBA bitmap', 'rgba': 'Raw RGBA bitmap', 'svg': 'Scalable Vector Graphics', 'svgz': 'Scalable Vector Graphics', 'tif': 'Tagged Image File Format', 'tiff': 'Tagged Image File Format'}
我們有?fig?對象,因此我們可以將圖像保存成多種格式:
fig.savefig('sales.png', transparent=False, dpi=80, bbox_inches="tight")
結論
該版本將圖表保存為不透明背景的?png?文件。我還指定?dpi?和?bbox_inches="tight"?以最小化多余空白。最后,希望該方法可以幫助大家理解如何更有效地使用?Matplotlib?進行日常數據分析。
原文鏈接:http://pbpython.com/effective-matplotlib.html
精彩活動
福利 · 閱讀 | 免費申請讀大數據新書 第23期
推薦閱讀
2017年數據可視化的七大趨勢!?
全球100款大數據工具匯總(前50款)?
論大數據的十大局限
大數據時代的10個重大變革
大數據七大趨勢 第一個趨勢是物聯網
Q:?你還知道哪些實現數據可視化的方法和工具?
歡迎留言與大家分享
請把這篇文章分享給你的朋友
轉載 / 投稿請聯系:hzzy@hzbook.com
更多精彩文章,請在公眾號后臺點擊“歷史文章”查看
總結
以上是生活随笔為你收集整理的教程 | 如何优雅而高效地使用Matplotlib实现数据可视化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何判断程序猿在做什么
- 下一篇: linux服务与进程管理sup,linu