matplotlib繪圖和可視化
matplotlib是一個用于創(chuàng)建出版質(zhì)量圖表的桌面繪圖包(主要是2D方面)。繪圖是數(shù)據(jù)分析工作中最重要的任務之一,是探索過程的一部分。
import matplotlib.pyplot as plt
from pandas import Series,DataFrame
import pandas as pd
import numpy as np
from numpy.random import randn
plt.plot(np.arange(15))
plt.show()

Figure和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--')
"k--"是一個線型選項,用于告訴matplotlib繪制黑色虛線圖。上面那些由fig.add_subplot所返回的對象是AxesSubplot對象,直接調(diào)用它們的實例方法就可以在其他空著的格子里面畫圖
_=ax1.hist(np.random.randn(100),bins=20,color='r',alpha=0.3)
ax2.scatter(np.arange(30),np.arange(30)+3*np.random.randn(30))
plt.show()

plt.subplots,它可以創(chuàng)建一個新的Figure,并返回一個含有已創(chuàng)建的subplot對象的NumPy數(shù)組
fig,axes=plt.subplots(2,3)
axes
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000000012981F98>,
<matplotlib.axes._subplots.AxesSubplot object at 0x0000000012835FD0>,
<matplotlib.axes._subplots.AxesSubplot object at 0x00000000129EAFD0>],
[<matplotlib.axes._subplots.AxesSubplot object at 0x000000001298C9B0>,
<matplotlib.axes._subplots.AxesSubplot object at 0x00000000127EDA20>,
<matplotlib.axes._subplots.AxesSubplot object at 0x00000000125DBEB8>]], dtype=object)

調(diào)整subplot周圍的間距
Figure的subplots_adjust方法可以修改間距
#subplots_adjust(left=None,bottom=None,right=None,top=None,wpace=None,hspace=None)
fig,axes=plt.subplots(2,2,sharex=True,sharey=True)
for i in range(2):
for j in range(2):
axes[i,j].hist(randn(500),bins=50,color='k',alpha=0.6)
plt.subplots_adjust(wspace=0,hspace=0)
plt.show()

顏色、標記和線型
matplotlib的plot函數(shù)接受一組X和Y坐標,還可以接受一個表示顏色和線型的字符串縮寫
ax.plot(x,y,'g--') #根據(jù)x和y繪制綠色虛線
ax.plot(x,y,linestyle='--',color='g')
plt.plot(np.random.randn(30).cumsum(),'ko--')
plt.show()

可以把它寫成更為明確的方式
plt.plot(np.random.randn(30).cumsum(),color='b',linestyle='dashed',marker='o')
plt.show()

在線型圖中,非實際數(shù)據(jù)點默認是按線性方式插值的??梢酝ㄟ^drawstyle選項修改
data=np.random.randn(30).cumsum()
plt.plot(data,'k--',label='Default')
plt.show()

plt.plot(data,'k-',color='b',drawstyle='steps-post',label='steps-post')
plt.show()

plt.plot(data,'k-',color='b',drawstyle='steps-post',label='steps-post')
plt.legend(loc='best')
plt.show()

刻度、標簽和圖例
設置標題、軸標簽、刻度以及刻度標簽
創(chuàng)建一個簡單的圖像并繪制一段隨機漫步
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum())
plt.show()

可以使用set_xticks和set_xticklabels修改X軸的刻度
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum())
#用set_xticks修改X軸的刻度
ticks=ax.set_xticks([0,250,500,750,1000])
#可以通過set_xticklabels將任何其他的值用作標簽
labels=ax.set_xticklabels(['one','two','three','four','five'],rotation=30,fontsize='small')
#用set_title給圖表設置一個標題
ax.set_title('My first matplotlib plot')
#為X軸設置一個名稱
ax.set_xlabel('Stages')
plt.show()

添加圖例(legend)
在添加subplot的時候傳入label參數(shù)來添加圖例
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
ax.plot(np.random.randn(1000).cumsum(),'k',label='one',color='r')
ax.plot(np.random.randn(1000).cumsum(),'k--',label='two',color='g')
ax.plot(np.random.randn(1000).cumsum(),'k.',label='three',color='b')
ax.legend(loc='best')
plt.show()

調(diào)用ax.legend()或plt.legend()來自動創(chuàng)建圖例
loc告訴matplotlib要將圖例放在哪,'beat'里面可以顯示確定的位置,如下:
best
upper right
upper left
lower left
lower right
right
center left
center right
lower center
upper center
center
如果要從圖例中去除一個或多個元素,不傳入label或傳入label='nolegend'
注解以及在Subplot上繪圖
注解可以是文本、箭頭或其他圖形等,通過text、arrow和annotate等函數(shù)進行添加。text可以將文本繪制在圖表的指定坐標(x,y),還可以加上一些自定義格式
ax.text(x,y,"hello world!",Family='monospace',fontsize=10)
例如,我們根據(jù)2007年以來的標準普爾500指數(shù)收盤價格(來自Yahoo!Finance)繪制一張曲線圖,并標出2008年到2009年金融危機期間的一些重要日期。結(jié)果如下圖所示
from datetime import datetime
import pandas as pd
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
data=pd.read_csv('examples/spx.csv',index_col=0,parse_dates=True)
spx=data['SPX']
spx.plot(ax=ax,style='k-')
crisis_data=[
(datetime(2007,10,11),'Peak of bull market'),
(datetime(2008,3,12),'Bear Stearns Fails'),
(datetime(2008,9,15),'Lehman Bankruptcy')]
for date,label in crisis_data:
ax.annotate(label,xy=(date,spx.asof(date)+50),
xytext=(date,spx.asof(date)+200),
arrowprops=dict(facecolor='black'),
horizontalalignment='left',verticalalignment='top')
# 放大到2007-2010
ax.set_xlim(['1/1/2007','1/1/2011'])
ax.set_ylim([600,1800])
ax.set_title('Important dates in 2008-2009 financial crisis')
plt.show()

要在圖表中添加一個圖形,你需要創(chuàng)建一個塊對象shp,然后通過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='r',alpha=0.6)
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)
plt.show()

將圖表保存到文件
利用plt.savefig可以將當前圖表保存到文件。該方法相當于Figure對象的實例方法savefig
plt.savefig('figpath.svg')
在發(fā)布圖片時最常用到兩個重要的選項是dpi(控制“每英寸點數(shù)”分辨率)和bbox_inches(可以剪除當前圖表周圍的空白部分)。要得到一張帶有最小白邊且分辨率為400DPI的PNG圖片可以這樣做:
plt.savefig('figpath.png',dpi=400,bbox_inches='tight')
savefig并非一定要寫入磁盤,也可以寫入任何文件型的對象,比如StringIO。其中,這個在Web上提供動態(tài)生成的圖片是很實用
from io import StringIO
plt.savefig(buffer)
plot_data=buffer.getvaule()

matplotlib配置
matplotlib自帶一些配色方案,以及為生成出版質(zhì)量的圖片而設定的默認配置信息,可以管理圖像大小、subplot邊距、配色方案、字體大小、網(wǎng)格類型等。操作matplotlib配置系統(tǒng)的方式主要有兩種。第一種是Python編程方式,即利用rc方法
將全局的圖像默認大小設置為10×10
plt.rc('figure',figsize=(10,10))
rc的第一個參數(shù)是希望自定義的對象,如'figure'、'axes'、'xtick'、'ytick'、'grid'、'legend'等。其后可以跟上一系列的關鍵字參數(shù)。最簡單的辦法是將這些選項寫成一個字典
font_opinions={'family':'monospace','weight':'bold','size':'samll'}
plt.rc('font',**font_options)
pandas中的繪圖函數(shù)
pandas在線文檔將會是最好的繪圖函數(shù)學習資源。
線型圖
Series對象的索引會被傳給matplotlib,并用以繪制X軸。可以通過use_index=False禁用該功能。
X軸的刻度和界限可以通過xticks和xlim選項進行調(diào)節(jié),Y軸就用yticks和ylim
s=Series(np.random.randn(10).cumsum(),index=np.arange(0,100,10))
s.plot()
plt.show()

pandas的大部分繪圖方法都有一個可選的ax參數(shù),它可以是一個matplotlib的subplot對象。這使你能夠在網(wǎng)格布局中更為靈活地處理subplot的位置。
DataFrame的plot方法會在一個subplot中為各列繪制一條線,并自動創(chuàng)建圖例。
df=DataFrame(np.random.randn(10,4).cumsum(0),columns=['A','B','C','D'],index=np.arange(0,100,10))
df.plot()
plt.show()

注意: plot的其他關鍵字參數(shù)會被傳給相應的matplotlib繪圖函數(shù),所以要更深入地自定義圖表,就必須學習更多有關matplotlib API的知識。
柱狀圖
在生成線型圖的代碼中加上kind='bar'(垂直柱狀圖)或kind='barh'(水平柱狀圖)即可生成柱狀圖。這時,Series和DataFrame的索引將會被用作X(bar)或Y(barh)刻度
fig,axes=plt.subplots(2,1)
data=Series(np.random.rand(16),index=list('abcdefghijklmnop'))
data.plot(kind='bar',ax=axes[0],color='g',alpha=0.6)
data.plot(kind='barh',ax=axes[1],color='g',alpha=0.6)
plt.show()

對于DataFrame,柱狀圖會將每一行的值分為一組
df=DataFrame(np.random.rand(6,4),index=['one','two','three','four','five','six'],columns=['A','B','C','D'])
df
| A | B | C | D | |
|---|---|---|---|---|
| one | 0.381932 | 0.042627 | 0.290334 | 0.700356 |
| two | 0.212308 | 0.519060 | 0.241667 | 0.653755 |
| three | 0.223746 | 0.233344 | 0.714892 | 0.620117 |
| four | 0.401946 | 0.862935 | 0.874891 | 0.862926 |
| five | 0.680490 | 0.879683 | 0.562349 | 0.036203 |
| six | 0.791145 | 0.873458 | 0.604575 | 0.479191 |
df.plot(kind='bar')
plt.show()

DataFrame各列的名稱"Genus"被用作了圖例的標題。設置stacked=True即可為DataFrame生成堆積柱狀圖,這樣每行的值就會被堆積在一起
提示:柱狀圖有一個非常不錯的用法:利用value_counts圖形化顯示Series中各值的出現(xiàn)頻率,比如s.value_counts ().plot(kind='bar')。
df.plot(kind='barh',stacked=True,alpha=0.8)
plt.show()

以本書的有關小費的數(shù)據(jù)集為例,假設我們想要做一張堆積柱狀圖以展示每天各種聚會規(guī)模的數(shù)據(jù)點的百分比。我用read_csv將數(shù)據(jù)加載進來,然后根據(jù)日期和聚會規(guī)模創(chuàng)建一張交叉表
tips=pd.read_csv('examples/tips.csv')
#如果通過tips.size,取到的是一整列的和
party_counts=pd.crosstab(tips.day,tips['size'])
party_counts
| 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 |
進行規(guī)格化,使得各行的和為1(必須轉(zhuǎn)換成浮點數(shù)),并生成圖表
party_counts=party_counts.ix[:,2:5]# 1個人和6個人的聚會都比較少
party_pcts=party_counts.div(party_counts.sum(1).astype(float),axis=0)
party_pcts
| size | 2 | 3 | 4 | 5 |
|---|---|---|---|---|
| day | ||||
| Fri | 0.888889 | 0.055556 | 0.055556 | 0.000000 |
| Sat | 0.623529 | 0.211765 | 0.152941 | 0.011765 |
| Sun | 0.520000 | 0.200000 | 0.240000 | 0.040000 |
| Thur | 0.827586 | 0.068966 | 0.086207 | 0.017241 |
通過該數(shù)據(jù)集就可以看出,聚會規(guī)模在周末會變大
直方圖和密度圖
直方圖(histogram)是一種可以對值頻率進行離散化顯示的柱狀圖。數(shù)據(jù)點被拆分到離散的、間隔均勻的面元中,繪制的是各面元中數(shù)據(jù)點的數(shù)量
以前面那個小費數(shù)據(jù)為例,通過Series的hist方法,我們可以生成一張“小費占消費總額百分比”的直方圖
tips['tip_pct']=tips['tip']/tips['total_bill']
tips['tip_pct'].hist(bins=50)
plt.show()

與此相關的一種圖表類型是密度圖,它是通過計算“可能會產(chǎn)生觀測數(shù)據(jù)的連續(xù)概率分布的估計”而產(chǎn)生的。一般的過程是將該分布近似為一組核(即諸如正態(tài)(高斯)分布之類的較為簡單的分布)。
調(diào)用plot時加上kind='kde'即可生成一張密度圖(標準混合正態(tài)分布KDE)
tips['tip_pct'].plot(kind='kde')
plt.show()
這兩種圖表常常會被畫在一起。直方圖以規(guī)格化形式給出(以便給出面元化密度),然后再在其上繪制核密度估計。接下來來看一個由兩個不同的標準正態(tài)分布組成的雙峰分布
comp1=np.random.normal(0,1,size=200)#N(0,1)
comp2=np.random.normal(10,2,size=200)# (10,4)
values=Series(np.concatenate([comp1,comp2]))
values.hist(bins=100,alpha=0.3,color='g',normed=True)
values.plot(kind='kde',style='k--')
plt.show()

散布圖
散布圖(scatter plot)是觀察兩個一維數(shù)據(jù)序列之間的關系的有效手段。matplotlib的scatter方法是繪制散布圖的主要方法
通過例子看看,首先加載了來自statsmodels項目的macrodata數(shù)據(jù)集,選擇其中幾列,然后計算對數(shù)差
macro=pd.read_csv('examples/macrodata.csv')
data=macro[['cpi','m1','tbilrate','unemp']]
trans_data=np.log(data).diff().dropna()
trans_data[-5:]
| 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 |
利用plt.scatter即可輕松繪制一張簡單的散布圖
plt.scatter(trans_data['m1'],trans_data['unemp'])
plt.title('Cahnges in log %s vs. log %s '%('m1','unemp'))
plt.show()

散布圖矩陣(scatter plot matrix)。
pandas提供了一個能從DataFrame創(chuàng)建散布圖矩陣的scatter_matrix函數(shù)。它還支持在對角線上放置各變量的直方圖或密度圖
pd.scatter_matrix(trans_data,diagonal='kde',alpha=0.3)
plt.show()
e:\python\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: pandas.scatter_matrix is deprecated. Use pandas.plotting.scatter_matrix instead
"""Entry point for launching an IPython kernel.

通過練習python matplotlib可視化的知識,學習到對數(shù)據(jù)繪圖的基礎知識,了解到matplotlib其他的繪圖接口 seaborn和 ggplot。
完善并深入練習還是需要去官方網(wǎng)站去查看相關的用法。
有興趣可以去官網(wǎng)查看手冊:https://matplotlib.org/