一、前言
matplotlib
是一個(gè)用于創(chuàng)建出版質(zhì)量圖表的桌面繪圖包(主要是2D方面)。該項(xiàng)目是由John Hunter于2002年啟動(dòng)的,其目的是為Python
構(gòu)建一個(gè)MATLAB
式的繪圖接口。matplotlib
和IPython
社區(qū)進(jìn)行合作,簡(jiǎn)化了從IPython shell
(包括現(xiàn)在的Jupyter notebook
)進(jìn)行交互式繪圖。matplotlib
支持各種操作系統(tǒng)上許多不同的GUI后端,而且還能將圖片導(dǎo)出為各種常見(jiàn)的矢量(vector)和光柵(raster)圖:PDF、SVG、JPG、PNG、BMP、GIF等。除了幾張,本書(shū)中的大部分圖都是用它生成的。
對(duì)于創(chuàng)建用于打印或網(wǎng)頁(yè)的靜態(tài)圖形,我建議默認(rèn)使用matplotlib
和附加的庫(kù),比如pandas
和seaborn
。對(duì)于交互式圖形以便在Web上發(fā)布,可以使用Plotly和Boken
學(xué)習(xí)本章代碼案例的最簡(jiǎn)單方法是在Jupyter notebook
進(jìn)行交互式繪圖。在Jupyter notebook中執(zhí)行下面的語(yǔ)句:%matplotlib notebook
二、matplotlib API 入門(mén)
1.引入matplotlib
,并創(chuàng)建簡(jiǎn)單的圖形
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(10)
plt.plot(data)
雖然seaborn
這樣的庫(kù)和pandas
的內(nèi)置繪圖函數(shù)能夠處理許多普通的繪圖任務(wù),但如果需要自定義一些高級(jí)功能的話就必須學(xué)習(xí)matplotlib
API。matplotlib
的示例庫(kù)和文檔是學(xué)習(xí)高級(jí)特性的最好資源。
2.matplotlib的圖像都位于Figure對(duì)象中。你可以用plt.figure創(chuàng)建一個(gè)新的Figure,但不能通過(guò)空Figure繪圖。必須用add_subplot創(chuàng)建一個(gè)或多個(gè)subplot才行:
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)
ax2 = fig.add_subplot(2, 2, 2)
ax3 = fig.add_subplot(2, 2, 3)
plt.plot(np.random.randn(50).cumsum(), 'k--') # 在最后一個(gè)用過(guò)的subplot上進(jìn)行繪制,隱藏創(chuàng)建figure和subplot的過(guò)程
提示:使用Jupyter notebook有一點(diǎn)不同,即每個(gè)小窗重新執(zhí)行后,圖形會(huì)被重置。因此,對(duì)于復(fù)雜的圖形,,你必須將所有的繪圖命令存在一個(gè)小窗里。
由fig.add_subplot所返回的對(duì)象是AxesSubplot對(duì)象,直接調(diào)用它們的實(shí)例方法就可以在其它空著的格子里面畫(huà)圖了
ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3)
ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))
3.plt.subplots,它可以創(chuàng)建一個(gè)新的Figure,并返回一個(gè)含有已創(chuàng)建的subplot
對(duì)象的NumPy
數(shù)組:fig, axes = plt.subplots(2, 3)
。可以輕松地對(duì)axes數(shù)組進(jìn)行索引,就好像是一個(gè)二維數(shù)組一樣,例如axes[0,1]。還可以通過(guò)sharex
和sharey
指定subplot
應(yīng)該具有相同的X軸或Y軸。在比較相同范圍的數(shù)據(jù)時(shí),這也是非常實(shí)用的,否則,matplotlib
會(huì)自動(dòng)縮放各圖表的界限。

4.利用Figure的subplots_adjust
(也是個(gè)頂級(jí)函數(shù))方法可以輕而易舉地修改間距:subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=None, hspace=None)
,其中wspace
和hspace
用于控制寬度和高度的百分比,可以用作subplot
之間的間距。
5.在plot
函數(shù)中可以通過(guò)字符串來(lái)指定顏色和線型:ax.plot(x, y,'g--')
這種更為明確的方式也能得到同樣的效果:ax.plot(x, y, linestyle='--', color='g')
常用的顏色可以使用顏色縮寫(xiě),也可以指定顏色碼(例如,#CECECE
)
在IPython
和Jupyter
中使用plot?
可以查看文檔說(shuō)明。
6.線圖可以使用標(biāo)記強(qiáng)調(diào)數(shù)據(jù)點(diǎn)。因?yàn)?code>matplotlib可以創(chuàng)建連續(xù)線圖,在點(diǎn)之間進(jìn)行插值,因此有時(shí)可能不太容易看出真實(shí)數(shù)據(jù)點(diǎn)的位置。標(biāo)記也可以放到格式字符串中,但標(biāo)記類型和線型必須放在顏色后面:
from numpy.random import randn
plt.plot(randn(30).cumsum(), 'ko--')
plot(randn(30).cumsum(), color='k', linestyle='dashed', marker='o')
7.在線型圖中,非實(shí)際數(shù)據(jù)點(diǎn)默認(rèn)是按線性方式插值的??梢酝ㄟ^(guò)drawstyle
選項(xiàng)修改
data = np.random.randn(30).cumsum()
plt.plot(data,'k--', label='Default')
plt.plot(data,'k-', drawstyle='steps-post', label='steps-post')
plt.legend(loc='best')

筆記:你必須調(diào)用plt.legend(或使用ax.legend,如果引用了軸的話)來(lái)創(chuàng)建圖例,無(wú)論你繪圖時(shí)是否傳遞label標(biāo)簽選項(xiàng)。
8.pyplot接口的設(shè)計(jì)目的就是交互式使用,含有諸如xlim
、xticks
和xticklabels
之類的方法。它們分別控制圖表的范圍、刻度位置、刻度標(biāo)簽等。其使用方式有以下兩種:
- 調(diào)用時(shí)不帶參數(shù),則返回當(dāng)前的參數(shù)值(例如,
plt.xlim()
返回當(dāng)前的X軸繪圖范圍)。
- 調(diào)用時(shí)帶參數(shù),則設(shè)置參數(shù)值(例如,
plt.xlim([0,10])
會(huì)將X軸的范圍設(shè)置為0到10)。
所有這些方法都是對(duì)當(dāng)前或最近創(chuàng)建的AxesSubplot
起作用的。它們各自對(duì)應(yīng)subplot
對(duì)象上的兩個(gè)方法,以xlim
為例,就是ax.get_xlim
和ax.set_xlim
。
9. 設(shè)置標(biāo)題、軸標(biāo)簽、刻度以及刻度標(biāo)簽
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(np.random.randn(1000).cumsum()) # 創(chuàng)建隨機(jī)漫步數(shù)據(jù)
ticks = ax.set_xticks([0,250,500,750,1000]) # 改變x軸刻度
labels = ax.set_xticklabels(['one','two','three','four','five'], rotation=30, fontsize='small') # 設(shè)置軸標(biāo)簽
ax.set_title('My first matplotlib plot') # 設(shè)置題目
ax.set_xlabel('Stages') # 設(shè)置軸名稱
props ={
'title':'My first matplotlib plot',
'xlabel':'Stages'
}
ax.set(**props) # 設(shè)置題目和軸名稱
10.圖例(legend)是另一種用于標(biāo)識(shí)圖表元素的重要工具。最簡(jiǎn)單的是在添加subplot的時(shí)候傳入label參數(shù)。要從圖例中去除一個(gè)或多個(gè)元素,不傳入label
或傳入label='nolegend‘
即可。
fig = plt.figure(); ax = fig.add_subplot(1,1,1)
ax.plot(randn(1000).cumsum(),'k', label='one')
ax.plot(randn(1000).cumsum(),'k--', label='two')
ax.plot(randn(1000).cumsum(),'k.', label='three')
ax.legend(loc='best') # 必須調(diào)用legend方法才能顯示圖例
11.注解以及在Subplot上繪圖
- 注解和文字可以通過(guò)text、arrow和annotate函數(shù)進(jìn)行添加。text可以將文本繪制在圖表的指定坐標(biāo)(x,y),還可以加上一些自定義格式:
ax.text(x, y,'Hello world!', family='monospace', fontsize=10)
- 注解中可以既含有文本也含有箭頭。
- 要在圖表中添加一個(gè)圖形,你需要?jiǎng)?chuàng)建一個(gè)塊對(duì)象shp,然后通過(guò)
ax.add_patch(shp)
將其添加到subplot中:
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
rect = plt.Rectangle((0.2,0.75),0.4,0.15, color='k', alpha=0.3)
circ = plt.Circle((0.7,0.2),0.15, color='b', alpha=0.3)
pgon = plt.Polygon([[0.15,0.15],[0.35,0.4],[0.2,0.6]],
color='g', alpha=0.5)
ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)
12.將圖表保存到文件
plt.savefig
可以將當(dāng)前圖表保存到文件。該方法相當(dāng)于Figure
對(duì)象的實(shí)例方法savefig
。
參數(shù):
dpi:控制“每英寸點(diǎn)數(shù)”分辨率;
bbox_inches:可以剪除當(dāng)前圖表周圍的空白部分
plt.savefig('figpath.png', dpi=400, bbox_inches='tight')
savefig
并非一定要寫(xiě)入磁盤(pán),也可以寫(xiě)入任何文件型的對(duì)象,比如BytesIO
:
from io importBytesIO
buffer =BytesIO()
plt.savefig(buffer)
plot_data = buffer.getvalue()

13.matplotlib自帶一些配色方案,以及為生成出版質(zhì)量的圖片而設(shè)定的默認(rèn)配置信息。幾乎所有默認(rèn)行為都能通過(guò)一組全局參數(shù)進(jìn)行自定義,它們可以管理圖像大小、subplot邊距、配色方案、字體大小、網(wǎng)格類型等。一種Python
編程方式配置系統(tǒng)的方法是使用rc
方法。
- 要將全局的圖像默認(rèn)大小設(shè)置為10×10,可以執(zhí)行:
plt.rc('figure', figsize=(10,10))
rc
的第一個(gè)參數(shù)是希望自定義的對(duì)象,如'figure'、'axes'、'xtick'、'ytick'、'grid'、'legend'等。其后可以跟上一系列的關(guān)鍵字參數(shù)。一個(gè)簡(jiǎn)單的辦法是將這些選項(xiàng)寫(xiě)成一個(gè)字典:
font_options ={
'family':'monospace',
'weight':'bold',
'size':'small'
}
plt.rc('font',**font_options)
三、使用pandas和seaborn繪圖
在pandas
中,我們有多列數(shù)據(jù),還有行和列標(biāo)簽。pandas
自身就有內(nèi)置的方法,用于簡(jiǎn)化從DataFrame
和Series
繪制圖形。另一個(gè)庫(kù)seaborn簡(jiǎn)化了許多常見(jiàn)可視類型的創(chuàng)建。
提示:引入seaborn會(huì)修改matplotlib默認(rèn)的顏色方案和繪圖類型,以提高可讀性和美觀度。即使你不使用seaborn API,你可能也會(huì)引入seaborn,作為提高美觀度和繪制常見(jiàn)matplotlib圖形的簡(jiǎn)化方法。
1.Series和DataFrame都有一個(gè)用于生成各類圖表的plot方法。默認(rèn)情況下,它們所生成的是線型圖:
s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10))
s.plot()
該Series
對(duì)象的索引會(huì)被傳給matplotlib
,并用以繪制X軸。可以通過(guò)use_index=False
禁用該功能。X軸的刻度和界限可以通過(guò)xticks
和xlim
選項(xiàng)進(jìn)行調(diào)節(jié),Y軸就用yticks
和ylim
。


2.pandas
的大部分繪圖方法都有一個(gè)可選的ax參數(shù),它可以是一個(gè)matplotlib
的subplot
對(duì)象。這使你能夠在網(wǎng)格布局中更為靈活地處理subplot的位置。DataFrame
的plot
方法會(huì)在一個(gè)subplot
中為各列繪制一條線,并自動(dòng)創(chuàng)建圖例
df = pd.DataFrame(np.random.randn(10, 4).cumsum(0), columns=['A', 'B', 'C', 'D'], index=np.arange(0, 100, 10))
df.plot()
plot屬性包含一批不同繪圖類型的方法。例如,df.plot()
等價(jià)于df.plot.line()

筆記:plot的其他關(guān)鍵字參數(shù)會(huì)被傳給相應(yīng)的matplotlib繪圖函數(shù),所以要更深入地自定義圖表,就必須學(xué)習(xí)更多有關(guān)matplotlib API的知識(shí)。
3.plot.bar()和plot.barh()
分別繪制水平和垂直的柱狀圖。這時(shí),Series
和DataFrame
的索引將會(huì)被用作X(bar)或Y(barh)刻度
fig, axes = plt.subplots(2, 1)
data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop'))
data.plot.bar(ax=axes[0], color='k', alpha=0.7) # alpha設(shè)置透明度
data.plot.barh(ax=axes[1], color='k', alpha=0.7)
4.對(duì)于DataFrame,柱狀圖會(huì)將每一行的值分為一組,并排顯示
df = pd.DataFrame(np.random.rand(6, 4), index=['one', 'two', 'three', 'four', 'five', 'six'], columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))
df.plot.bar()

5.設(shè)置stacked=True
即可為DataFrame
生成堆積柱狀圖,這樣每行的值就會(huì)被堆積在一起:df.plot.barh(stacked=True, alpha=0.5)
筆記:柱狀圖有一個(gè)非常不錯(cuò)的用法:利用value_counts
圖形化顯示Series
中各值的出現(xiàn)頻率,比如s.value_counts().plot.bar()
。
6.做一張堆積柱狀圖以展示每天各種聚會(huì)規(guī)模的數(shù)據(jù)點(diǎn)的百分比。
In [75]: tips = pd.read_csv('pydata-book-2nd-edition/')
In [76]: party_counts = pd.crosstab(tips['day'], tips['size'])
In [77]: party_counts
Out[77]:
size 1 2 3 4 5 6
day
Fri 1 16 1 1 0 0
Sat 2 53 18 13 1 0
Sun 0 39 15 18 3 1
Thur 1 48 4 5 1 3
# Not many 1- and 6-person parties
In [78]: party_counts = party_counts.loc[:, 2:5]
In [79]: party_pcts = party_counts.div(party_counts.sum(1), axis=0) # 進(jìn)行規(guī)格化,使得各行的和為1
In [81]: party_pcts.plot.bar()
7.對(duì)于在繪制一個(gè)圖形之前,需要進(jìn)行合計(jì)的數(shù)據(jù),使用seaborn
可以減少工作量。seaborn
的繪制函數(shù)使用data參數(shù),它可能是pandas
的DataFrame
。其它的參數(shù)是關(guān)于列的名字。因?yàn)橐惶斓拿總€(gè)值有多次觀察,柱狀圖的值是tip_pct
的平均值。繪制在柱狀圖上的黑線代表95%
置信區(qū)間(可以通過(guò)可選參數(shù)配置)。
In [83]: import seaborn as sns
In [84]: %matplotlib inline # 在jupyter中輸入,避免無(wú)法顯示圖的問(wèn)題
In [85]: tips['tip_pct'] = tips['tip'] / (tips['total_bill'] - tips['tip'])
In [86]: tips.head()
Out[86]:
total_bill tip smoker day time size tip_pct
0 16.99 1.01 No Sun Dinner 2 0.063204
1 10.34 1.66 No Sun Dinner 3 0.191244
2 21.01 3.50 No Sun Dinner 3 0.199886
3 23.68 3.31 No Sun Dinner 2 0.162494
4 24.59 3.61 No Sun Dinner 4 0.172069
In [86]: sns.barplot(x='tip_pct', y='day', data=tips, orient='h')
In [87]: sns.barplot(x='tip_pct', y='day', hue='time', data=tips, orient='h') # 根據(jù)time列進(jìn)行顏色區(qū)分
In [90]: sns.set(style="whitegrid") # 設(shè)置圖形外觀

8.直方圖(histogram)是一種可以對(duì)值頻率進(jìn)行離散化顯示的柱狀圖。數(shù)據(jù)點(diǎn)被拆分到離散的、間隔均勻的面元中,繪制的是各面元中數(shù)據(jù)點(diǎn)的數(shù)量。
tips['tip_pct'].plot.hist(bins=50) # bins表示柱的數(shù)量
9.密度圖是通過(guò)計(jì)算“可能會(huì)產(chǎn)生觀測(cè)數(shù)據(jù)的連續(xù)概率分布的估計(jì)”而產(chǎn)生的。一般的過(guò)程是將該分布近似為一組核(即諸如正態(tài)分布之類的較為簡(jiǎn)單的分布)。因此,密度圖也被稱作KDE(Kernel Density Estimate,核密度估計(jì))圖。使用plot.kde和標(biāo)準(zhǔn)混合正態(tài)分布估計(jì)即可生成一張密度圖:tips['tip_pct'].plot.density()
10.seaborn的distplot
方法繪制直方圖和密度圖更加簡(jiǎn)單,還可以同時(shí)畫(huà)出直方圖和連續(xù)密度估計(jì)圖。作為例子,考慮一個(gè)雙峰分布,由兩個(gè)不同的標(biāo)準(zhǔn)正態(tài)分布組成:
In [96]: comp1 = np.random.normal(0, 1, size=200)
In [97]: comp2 = np.random.normal(10, 2, size=200)
In [98]: values = pd.Series(np.concatenate([comp1, comp2]))
In [99]: sns.distplot(values, bins=100, color='k')

11.點(diǎn)圖或散布圖是觀察兩個(gè)一維數(shù)據(jù)序列之間的關(guān)系的有效手段。在下面這個(gè)例子中,我加載了來(lái)自statsmodels
項(xiàng)目的macrodata
數(shù)據(jù)集,選擇了幾個(gè)變量,然后計(jì)算對(duì)數(shù)差:
In [100]: macro = pd.read_csv('examples/macrodata.csv')
In [101]: data = macro[['cpi', 'm1', 'tbilrate', 'unemp']]
In [102]: trans_data = np.log(data).diff().dropna()
In [103]: trans_data[-5:]
Out[103]:
cpi m1 tbilrate unemp
198 -0.007904 0.045361 -0.396881 0.105361
199 -0.021979 0.066753 -2.277267 0.139762
200 0.002340 0.010286 0.606136 0.160343
201 0.008419 0.037461 -0.200671 0.127339
202 0.008894 0.012202 -0.405465 0.042560
In [104]: sns.regplot('m1', 'unemp', data=trans_data) # 做一個(gè)散布圖,并加上一條線性回歸的線
In [107]: sns.pairplot(trans_data, diag_kind='kde', plot_kws={'alpha': 0.2}) # 生成散布圖矩陣,pairplot支持在對(duì)角線上放置每個(gè)變量的直方圖或密度估計(jì)
plot_kws
參數(shù)可以傳遞配置選項(xiàng)到非對(duì)角線元素上的圖形使用。

12.有多個(gè)分類變量的數(shù)據(jù)可視化的一種方法是使用小面網(wǎng)格。seaborn
有一個(gè)有用的內(nèi)置函數(shù)factorplot
,可以簡(jiǎn)化制作多種分面圖
sns.factorplot(x='day', y='tip_pct', hue='time', col='smoker', kind='bar', data=tips[tips.tip_pct 1])
sns.factorplot(x='day', y='tip_pct', row='time', col='smoker', kind='bar', data=tips[tips.tip_pct 1]) # 通過(guò)給每個(gè)時(shí)間值添加一行來(lái)擴(kuò)展分面網(wǎng)格
factorplot
支持其它的繪圖類型,如盒圖(它可以顯示中位數(shù),四分位數(shù),和異常值):
sns.factorplot(x='tip_pct', y='day', kind='box', data=tips[tips.tip_pct 0.5])

到此這篇關(guān)于Python數(shù)據(jù)分析之繪圖和可視化詳解的文章就介紹到這了,更多相關(guān)Python繪圖和可視化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Python數(shù)據(jù)分析之pandas比較操作
- Python數(shù)據(jù)分析入門(mén)之?dāng)?shù)據(jù)讀取與存儲(chǔ)
- Python數(shù)據(jù)分析入門(mén)之教你怎么搭建環(huán)境
- python學(xué)習(xí)之panda數(shù)據(jù)分析核心支持庫(kù)
- python數(shù)據(jù)分析之公交IC卡刷卡分析
- Python數(shù)據(jù)分析庫(kù)pandas高級(jí)接口dt的使用詳解
- 用Python 爬取貓眼電影數(shù)據(jù)分析《無(wú)名之輩》
- 高考要來(lái)啦!用Python爬取歷年高考數(shù)據(jù)并分析