您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何高效使用Python可視化工具Matplotlib,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
Matplotlib是Python中最常用的可視化工具之一,可以非常方便地創建海量類型的2D圖表和一些基本的3D圖表。
為什么對matplotlib都是負面評價?
在我看來,新用戶學習matplotlib之所以會面臨一定的挑戰,主要有以下幾個原因。
首先,matplotlib有兩種接口。***種是基于MATLAB并使用基于狀態的接口。第二種是面向對象的接口。為什么是這兩種接口不在本文討論的范圍之內,但是知道有兩種方法在使用matplotlib進行繪圖時非常重要。
兩種接口引起混淆的原因在于,在stack overflow社區和谷歌搜索可以獲得大量信息的情況下,新用戶對那些看起來有些相似但不一樣的問題,面對多個解決方案會感到困惑。從我自己的經歷說起。回顧一下我的舊代碼,一堆matplotlib代碼的混合——這對我來說非常混亂(即使是我寫的)。
關鍵點
matplotlib的新用戶應該學習使用面向對象的接口。
matplotlib的另一個歷史性挑戰是,一些默認風格選項相當沒有吸引力。 在R語言世界里,可以用ggplot生成一些相當酷的繪圖,相比之下,matplotlib的選項看起來有點丑。令人欣慰的是matplotlib 2.0具有更美觀的樣式,以及非常便捷對可視化的內容進行主題化的能力。
使用matplotlib我認為第三個挑戰是,當繪制某些東西時,應該單純使用matplotlib還是使用建立在其之上的類似pandas或者seaborn這樣的工具,你會感到困惑。任何時候都可以有多種方式來做事,對于新手或不常用matplotlib的用戶來講,遵循正確的路徑是具有挑戰性的。將這種困惑與兩種不同的API聯系起來,是解決問題的秘訣。
為什么堅持要用matplotlib?
盡管有這些問題,但是我慶幸有matplotlib,因為它非常強大。這個庫允許創建幾乎任何你可以想象的可視化。此外,圍繞著它還有一個豐富的python工具生態系統,許多更先進的可視化工具用matplotlib作為基礎庫。如果在python數據科學棧中進行任何工作,都將需要對如何使用matplotlib有一個基本的了解。這是本文的其余部分的重點——介紹一種有效使用matplotlib的基本方法。
基本前提
如果你除了本文之外沒有任何基礎,建議用以下幾個步驟學習如何使用matplotlib:
學習基本的matplotlib術語,尤其是什么是圖和坐標軸
始終使用面向對象的接口,從一開始就養成使用它的習慣
用基礎的pandas繪圖開始你的可視化學習
用seaborn進行更復雜的統計可視化
用matplotlib來定制pandas或者seaborn可視化
這幅來自matplotlib faq的圖非常經典,方便了解一幅圖的不同術語。
大多數術語都非常直接,但要記住的要點是,Figure是最終的圖像,可能包含一個或多個坐標軸。坐標軸代表一個單獨的劃分。一旦你了解這些內容,以及如何通過面向對象的API訪問它們,下面的步驟才能開始進行。
這些術語知識有另一個好處,當你在網上看某些東西時,就有了一個起點。如果你花時間了解了這一點,才會理解matplotlib API的其余部分。此外,許多python的高級軟件包,如seaborn和ggplot都依賴于matplotlib。因此,了解這些基礎知識后再學那些功能更強大的框架會容易一些。
***,我不是說你應該避免選擇例如ggplot(aka ggpy),bokeh,plotly或者altair等其他更好的工具。我只是認為你需要從對matplotlib + pandas + seaborn 有一個基本了解開始。一旦理解了基本的可視化技術,就可以探索其他工具,并根據自己的需要做出明智的選擇。
入門
本文的其余部分將作為一個入門教程,介紹如何在pandas中進行基本的可視化創建,并使用matplotlib自定義最常用的項目。一旦你了解了基本過程,進一步的定制化創建就相對比較簡單。
重點講一下我遇到的最常見的繪圖任務,如標記軸,調整限制,更新繪圖標題,保存圖片和調整圖例。
準備開始,我先引入庫并讀入一些數據:
import pandas as pd import matplotlib.pyplot as plt from 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中進行過一些數據處理/分析,所以請先從基本的繪圖開始。
定制化繪圖
假設你對這個繪圖的要點很滿意,下一步就是定制它。使用pandas繪圖功能定制(如添加標題和標簽)非常簡單。但是,你可能會發現自己的需求在某種程度上超越該功能。這就是我建議養成這樣做的習慣的原因:
fig, ax = plt.subplots() top_10.plot(kind='barh', y="Sales", x="Name", ax=ax)
得到的圖看起來與原始圖看起來相同,但是我們向plt.subplots() 添加了一個額外的調用,并將ax傳遞給繪圖函數。為什么要這樣做? 記得當我說在matplotlib中要訪問坐標軸和數字至關重要嗎?這就是我們在這里完成的工作。將來任何定制化都將通過ax或fig對象完成。
我們得益于pandas快速繪圖,獲得了訪問matplotlib的所有權限。我們現在可以做什么呢?用一個例子來展示。另外,通過命名約定,可以非常簡單地把別人的解決方案改成適合自己獨特需求的方案。
假設我們要調整x限制并更改一些坐標軸的標簽?現在坐標軸保存在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');
下面是一個快捷方式,可以用來更改標題和兩個標簽:
Python 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() 函數,可以用英寸定義figsize。也可以用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()。
在這個例子中,我們將繪制一條平均線,并顯示三個新客戶的標簽。 下面是完整的代碼和注釋,把它們放在一起。
# 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來指定大小,這樣對新用戶來說比較清晰。在示例代碼中,經常看到像1,2這樣的變量。我覺得使用命名的參數,之后在查看代碼時更容易理解。
用sharey = True這個參數,以便yaxis共享相同的標簽。
這個例子也很好,因為各個坐標軸被解壓縮到ax0和ax1。有這些坐標軸軸,你可以像上面的例子一樣繪制圖形,但是在ax0和ax1上各放一個圖。
Python
# 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內聯指令來顯示圖形。但是很多時候,需要以特定格式保存數字,和其他內容一起展示。
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”來盡量減少多余的空格。
關于“如何高效使用Python可視化工具Matplotlib”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。