matplotlib

matplotlib基礎(chǔ)

matplotlib是面向?qū)ο蟮睦L圖工具包,繪制的圖形中的每一個(gè)元素都是一個(gè)對(duì)象,可以修改這些對(duì)象的屬性,從而改變圖樣式。

matplotlib中主要繪圖對(duì)象列表如下:

  • Figure對(duì)象,可以想象為一張畫(huà)布;
  • Axes對(duì)象,字面理解為坐標(biāo)軸也可以認(rèn)為時(shí)子圖,在一個(gè)Figure對(duì)象中可以包含多個(gè)Axes對(duì)象,也就是說(shuō)一張畫(huà)布可以包含多個(gè)子圖;* Line2D對(duì)象,代表線條;
  • Text對(duì)象,代表了文字;

雖然matplotlib是面向?qū)ο蟮睦L圖工具包,但是也提供了一些常用的繪圖方法,可以直接調(diào)用plt模塊相關(guān)方法就可以完成繪圖需求,這是因?yàn)閜lt模塊內(nèi)部保存了當(dāng)前的Figure對(duì)象信息,當(dāng)使用plt的相關(guān)方法繪圖時(shí),底層實(shí)際調(diào)用了當(dāng)前Figure對(duì)象的相關(guān)方法??梢酝ㄟ^(guò)plt.gcf()和plt.gca()分別獲取當(dāng)前用于繪圖的Figure和Axes對(duì)象。

通過(guò)plt.figure()創(chuàng)建一個(gè)新的Figure對(duì)象,然后在此Figure對(duì)象上創(chuàng)建Axies對(duì)象:

In [1]: import numpy as np

In [2]: import matplotlib.pyplot as plt

In [3]: fig1 = plt.figure()

In [4]: ax1 = fig1.add_subplot(1, 1, 1)

In [5]: fig1
Out[5]: <matplotlib.figure.Figure at 0x2b4d0bdf4e0>

In [6]: plt.gcf()
Out[6]: <matplotlib.figure.Figure at 0x2b4d0bdf4e0>

In [7]: ax1
Out[7]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0bff780>
In [9]: plt.gca()
Out[9]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0bff780>

In [10]: fig2 = plt.figure()

In [11]: ax2 = fig2.add_subplot(1, 1, 1)

In [12]: fig2
Out[12]: <matplotlib.figure.Figure at 0x2b4d0f602e8>

In [13]: plt.gcf()
Out[13]: <matplotlib.figure.Figure at 0x2b4d0f602e8>

In [14]: ax2
Out[14]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0f882e8>

In [15]: plt.gca()
Out[15]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d0f882e8>

每當(dāng)創(chuàng)建新的Figure對(duì)象時(shí),plt.gcf()獲取到的當(dāng)前的Figure對(duì)象也變成了新創(chuàng)建的Figure對(duì)象,因?yàn)樗鼈兊膬?nèi)存地址相同。fig1.add_subplot(1, 1, 1)方法,用于在Figure對(duì)象上創(chuàng)建一個(gè)新的Axes對(duì)象,由于Figure可以包含多個(gè)Axes對(duì)象,所以這里的參數(shù)含義是說(shuō),添加一個(gè)Axes對(duì)象到布局為一行一列的第一個(gè)位置上。
在Figure對(duì)象上插入四個(gè)Axes對(duì)象,布局為兩行兩列:

In [16]: fig = plt.figure()

In [17]: ax1 = fig.add_subplot(2, 2, 1)

In [18]: ax2 = fig.add_subplot(2, 2, 2)

In [19]: ax3 = fig.add_subplot(2, 2, 3)

In [20]: ax1.plot(np.random.randn(50).cumsum(), 'k--')
Out[20]: [<matplotlib.lines.Line2D at 0x2b4d1ab5550>]

In [21]: _ = ax2.hist(np.random.randn(100), bins=20, color='k')

In [22]: ax3.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))
Out[22]: <matplotlib.collections.PathCollection at 0x2b4d1b1f9b0>

In [23]: fig.show()

以上代碼,首先創(chuàng)建一個(gè)Figure對(duì)象,然后插入3個(gè)Axes對(duì)象,接著分別在Axes對(duì)象上繪制了累積和線圖,直方圖以及散點(diǎn)圖,最后通過(guò)fig.show()方法顯示出圖形如下:


Figure_1.png

常用屬性設(shè)置

matplotlib繪制的圖形可以設(shè)置各種屬性,如坐標(biāo)系的刻度,標(biāo)題,標(biāo)簽等屬性。

In [24]: fig = plt.figure()

In [25]: ax = fig.add_subplot(1, 1, 1)

In [26]: # 設(shè)置標(biāo)題

In [27]: ax.set_title("Axes Example")
Out[27]: Text(0.5,1,'Axes Example')

In [28]: major_ticks = np.arange(0, 101, 20)

In [29]: minor_ticks = np.arange(0, 101, 5)

In [30]: # 設(shè)置刻度

In [31]: ax.set_xticks(major_ticks)
In [33]: ax.set_xticks(minor_ticks, minor=True)
In [34]: ax.set_yticks(major_ticks)
In [35]: ax.set_yticks(minor_ticks, minor=True)
In [36]: # 設(shè)置X, Y軸標(biāo)簽

In [37]: ax.set_xlabel("X axis")
Out[37]: Text(0.5,0,'X axis')

In [38]: ax.set_ylabel("Y axis")
Out[38]: Text(0,0.5,'Y axis')

In [39]: # 設(shè)備網(wǎng)格
In [41]: ax.grid(which='minor', alpha=0.2)

In [42]: ax.grid(which='major', alpha=0.5)

In [43]: # 添加文字

In [44]: ax.text(42.5, 50, "shiyanlou")
Out[44]: Text(42.5,50,'shiyanlou')

In [45]: fig.show()

執(zhí)行以上代碼,繪制的圖形如下:


Figure_2.png

以上代碼首先創(chuàng)建了一個(gè)Figure對(duì)象,接著創(chuàng)建了唯一一個(gè)Axes對(duì)象,后續(xù)的所有屬性都基于該Axes對(duì)象設(shè)置:

  • ax.set_title 設(shè)置圖形的標(biāo)題;
  • ax.set_xticks 設(shè)置X軸的刻度,其中minor=True參數(shù)表示設(shè)置更小的刻度;
  • ax.set_yticks 設(shè)置Y軸的刻度;
  • ax.set_xlabel 設(shè)置X軸的標(biāo)簽;
  • ax.set_ylabel 設(shè)置X軸的標(biāo)簽;
  • ax.grid 開(kāi)啟圖形的刻度網(wǎng)格,其中minor=True參數(shù)表示顯示小刻度的網(wǎng)格;
  • ax.text 為圖形添加文字,前兩個(gè)參數(shù)表示添加的文字在坐標(biāo)系中的位置;

繪制曲線的顏色,設(shè)置圖例,代碼如下:

In [46]: x = np.linspace(0, 1, 100)

In [47]: fig = plt.figure()

In [48]: ax = fig.add_subplot(1, 1, 1)

In [49]: ax.set_title("shiyanlou")
Out[49]: Text(0.5,1,'shiyanlou')

In [50]: ax.plot(x, x ** (1/8), 'b--', label=r'$y = x^{1/8}$')
Out[50]: [<matplotlib.lines.Line2D at 0x2b4d1453908>]

In [51]: ax.plot(x, x ** 8, 'r--', label=r'$y = x^{8}$')
Out[51]: [<matplotlib.lines.Line2D at 0x2b4d1453f98>]

In [52]: ax.plot(x, x ** (1/2), 'r.', label=r'$y = x^{1/2}$')
Out[52]: [<matplotlib.lines.Line2D at 0x2b4d146c358>]

In [53]: ax.plot(x, x ** 2, 'b.', label=r'$y = x^{2}$')
Out[53]: [<matplotlib.lines.Line2D at 0x2b4d1453588>]

In [54]: ax.plot(x, x, 'g-', label=r'$y = x$')
Out[54]: [<matplotlib.lines.Line2D at 0x2b4d1453e48>]

In [55]: ax.legend()
Out[55]: <matplotlib.legend.Legend at 0x2b4d1453128>

In [56]: ax.axis([0, 1, 0, 1])
Out[56]: [0, 1, 0, 1]
In [58]: fig.show()

圖形顯示如下:


Figure_3.png

在上面的代碼中,通過(guò) np.linspace(0, 1, 100) 創(chuàng)建了 100 個(gè)值,這些值平均分布在 0 到 1 的范圍內(nèi)。接著我們?cè)?Axes 對(duì)象上繪制了 5 條曲線,這 5 條曲線分別對(duì)應(yīng)于 5 個(gè)函數(shù),函數(shù)名稱已經(jīng)通過(guò)圖例的形式顯示在圖形上了。

其中,我們使用類(lèi)似于 ax.plot(x, x ** (1/8), 'b--', label=r'y = x^{1/8}y=x
1/8
') 方法繪制曲線,該方法有四個(gè)參數(shù),前兩個(gè)參數(shù)分別對(duì)應(yīng)于 X, Y 軸的數(shù)據(jù),繪圖時(shí)會(huì)根據(jù) x 和 x ** (1/8) 值序列確定曲線的位置。第三個(gè)參數(shù) b-- 代表繪制的曲線是 blue 藍(lán)色,樣式是虛線。matplotlib 中有多種指定線條顏色和樣式的辦法,如 r-- 指明紅色虛線,r. 代表紅色點(diǎn),更多的樣式可以參考 matplotlib 文檔。最后一個(gè)參數(shù) label=r'y = x^{1/8}y=x
1/8
') 設(shè)置了線條的標(biāo)簽,該標(biāo)簽文字內(nèi)容是數(shù)學(xué)公式,matplotlib 支持 LaTeX 語(yǔ)法顯示各種數(shù)學(xué)公式。

有的時(shí)候,我們想在圖形上顯示曲線標(biāo)簽信息,這個(gè)時(shí)候可以使用 ax.legend() 方法,該方法使用曲線的標(biāo)簽信息(也就是繪制曲線是傳入的 label 參數(shù))自動(dòng)生成圖例,并將圖例放到圖形合適的位置。

最后為了方便查看圖形,我們將圖形的視口坐標(biāo)設(shè)置成了 [0, 1, 0, 1] ,代表X, Y坐標(biāo)軸范圍都設(shè)置為 0 到 1。如果圖形顯示范圍超過(guò)了 0 到 1 的范圍,則會(huì)自動(dòng)截取 0 到 1 范圍內(nèi)的圖形進(jìn)行顯示。

matplotlib 繪圖時(shí)可以設(shè)置很多屬性,比如設(shè)置注解,設(shè)置外部圖片等,這些都可以通過(guò)調(diào)用 Axes 對(duì)象相應(yīng)方法進(jìn)行,更多的用法可以查看 Axes 對(duì)象 API 文檔。

常用圖形

線形圖

線性圖更多時(shí)候是用來(lái)觀察變量之間的函數(shù)關(guān)系,如果滿足y = 2x的線性關(guān)系,那么繪制的圖形是一條直線,如果沒(méi)關(guān)系,則是一堆涂鴉。
使用Axes.plot方法繪制線形圖:

In [78]: fig1 = plt.figure()

In [79]: ax1 = fig1.add_subplot(1, 1, 1)

In [80]: x = np.random.randn(100)

In [81]: y = np.random.randn(100)
In [83]: ax1.plot(x, y)
Out[83]: [<matplotlib.lines.Line2D at 0x2b4d2a6ba58>]

In [84]: fig1.show()

以上代碼創(chuàng)建了兩個(gè)隨機(jī)的數(shù)值序列,這兩個(gè)數(shù)值序列之間理論上沒(méi)有任何關(guān)系,顯示的圖形如下:


Figure_4.png

直方圖

直方圖可以顯示數(shù)據(jù)分布情況,X 軸一般是統(tǒng)計(jì)的樣本,而 Y 是樣本對(duì)應(yīng)的統(tǒng)計(jì)度量。為了構(gòu)建直方圖,第一步是將值的范圍分段,即將整個(gè)值的范圍分成一系列間隔,然后計(jì)算每個(gè)間隔中有多少值。 這些值通常被指定為連續(xù)的,不重疊的變量間隔。 間隔必須相鄰,并且通常是(但不是必須的)相等的大小。在 matplotlib 中可以使用 Axes.hist 方法繪制直方圖:

In [85]: fig2 = plt.figure()

In [86]: ax2 = fig2.add_subplot(1, 1, 1)

In [87]: data = np.random.normal(0, 20, 1000)

In [88]: bins = np.arange(-100, 100, 5)
In [90]: ax2.hist(data, bins=bins)
Out[90]:
(array([   0.,    0.,    0.,    0.,    0.,    1.,    0.,    2.,    2.,
           4.,    8.,    9.,   14.,   30.,   39.,   60.,   73.,   83.,
          88.,  100.,   80.,  103.,   75.,   69.,   58.,   44.,   25.,
           7.,   12.,    7.,    4.,    0.,    2.,    1.,    0.,    0.,
           0.,    0.,    0.]),
 array([-100,  -95,  -90,  -85,  -80,  -75,  -70,  -65,  -60,  -55,  -50,
         -45,  -40,  -35,  -30,  -25,  -20,  -15,  -10,   -5,    0,    5,
          10,   15,   20,   25,   30,   35,   40,   45,   50,   55,   60,
          65,   70,   75,   80,   85,   90,   95]),
 <a list of 39 Patch objects>)

In [91]: fig2.show()

上面的代碼首先通過(guò) np.random.normal 方法,在 0 到 20 的范圍產(chǎn)生 1000 個(gè)符合正態(tài)分布的數(shù)據(jù)值,然后通過(guò) np.arange(-100, 100, 5) 創(chuàng)建了 X 軸的區(qū)間刻度。創(chuàng)建的圖形類(lèi)似下圖:


Figure_5.png

散點(diǎn)圖

散點(diǎn)圖,將所有的數(shù)據(jù)值在圖形中繪制成點(diǎn),這樣有多少數(shù)據(jù)值在圖形中就會(huì)有多少個(gè)點(diǎn)。通過(guò)這些數(shù)據(jù)點(diǎn)可以看出數(shù)據(jù)值的分布模式,比如是否有聚類(lèi)模式,或者相關(guān)關(guān)系或者發(fā)現(xiàn)離群點(diǎn)。在 matplotlib 中可以通過(guò) Axes.scatter 繪制散點(diǎn)圖:

In [92]: fig3 = plt.figure()

In [93]: ax3 = fig3.add_subplot(1, 1, 1)

In [94]: x = np.arange(1, 101)

In [95]: y = 20 + 3 * x + np.random.normal(0, 60, 100)

In [96]: ax3.scatter(x, y)
Out[96]: <matplotlib.collections.PathCollection at 0x2b4d4747198>

In [97]: fig3.show()

為了模擬散點(diǎn)圖,先通過(guò) np.arange(1, 101) 創(chuàng)建了 100 個(gè)數(shù)據(jù)值,接著基于此創(chuàng)建了 100 個(gè) Y 軸數(shù)據(jù),可以看到這里兩組數(shù)據(jù)值之間有相關(guān)關(guān)系,因?yàn)槭腔诰€性關(guān)系然后加上隨機(jī)數(shù)生成的,繪制的散點(diǎn)圖也證明了這點(diǎn)(圖形向上傾斜):

Figure_6.png

箱線圖

箱線圖可以看出數(shù)據(jù)的分散程度,異常值等信息,箱線圖根據(jù)一組數(shù)據(jù)的以下5個(gè)統(tǒng)計(jì)值進(jìn)行繪制:

  • 最小值
  • 第1四分位數(shù)
  • 中位數(shù)
  • 第3四分位數(shù)
  • 最大值

其中四分位數(shù),是指將一組數(shù)據(jù)值按大小排序后分成四等分,每一部分包含 1/4 的數(shù)據(jù),這種劃分的分割點(diǎn)就是四分位數(shù)。其中第1部分和第2部分的分割點(diǎn)稱為第1分位數(shù)Q 1, 也被稱為第25百分位數(shù),第3部分和第4部分的分割點(diǎn)稱為第3四分位數(shù) Q 3,也被稱為第75百分位數(shù)。而第二部分和第三部分的分割點(diǎn)是第2四分?jǐn)?shù),也就是中位數(shù)。其中四分位距 IQRIQR 是指第三四分位數(shù)和第一分四分位數(shù)的差,也就是IQR=Q 3?Q 1。四分位距反映了中間 50% 數(shù)據(jù)的離散程度,數(shù)值越小代表數(shù)據(jù)越集中,越大代表數(shù)據(jù)越分散。

在 matplotlib 中可以使用 Axes.boxplot 方法繪制箱線圖:

In [98]: fig4 = plt.figure()

In [99]: ax4 = fig4.add_subplot(1, 1, 1)

In [100]: # 產(chǎn)生50個(gè)小于100的隨機(jī)數(shù)

In [101]: spread = np.random.rand(50) * 100

In [102]: # 產(chǎn)生25個(gè)值為50的數(shù)據(jù)

In [103]: center = np.ones(25) * 50

In [104]: # 異常值

In [105]: outlier_high = np.random.rand(10) * 100 +100

In [106]: outlier_low = np.random.rand(10) * -100

In [107]: data = np.concatenate((spread, center, outlier_high, outlier_low), 0)

In [108]: ax4.boxplot(data)
Out[108]:
{'boxes': [<matplotlib.lines.Line2D at 0x2b4d507eb70>],
 'caps': [<matplotlib.lines.Line2D at 0x2b4d5087438>,
  <matplotlib.lines.Line2D at 0x2b4d508e828>],
 'fliers': [<matplotlib.lines.Line2D at 0x2b4d508ef28>],
 'means': [],
 'medians': [<matplotlib.lines.Line2D at 0x2b4d508eb00>],
 'whiskers': [<matplotlib.lines.Line2D at 0x2b4d507ec18>,
  <matplotlib.lines.Line2D at 0x2b4d5087668>]}

In [109]: fig4.show()

上面代碼中,我們特意創(chuàng)建data數(shù)據(jù),可以推斷出該數(shù)據(jù)的中位數(shù)是50,還有一些其他異常值,繪制圖形如下:


Figure_7.png

Pandas繪圖

Pandas高度整合了matplotlib,可以直接調(diào)用DataFrame對(duì)象的某些方法進(jìn)行繪圖,更加方便的時(shí)候DataFrame的標(biāo)簽信息會(huì)自動(dòng)繪制到圖形上。

直接在Series對(duì)象上繪制線型圖,代碼如下:


Figure_8.png

在DataFrame對(duì)象上繪制箱線圖:

In [117]: df = pd.DataFrame(np.random.rand(5, 4), columns=['A', 'B', 'C', 'D'])

In [118]: df.boxplot()
Out[118]: <matplotlib.axes._subplots.AxesSubplot at 0x2b4d8f7a4e0>

In [119]: plt.show()
Figure_9.png

其它繪圖工具

Seaborn 建立在 matplotlib 之上,提供了更高級(jí)更方便的使用方式。
通過(guò) Seaborn 可以很方面繪制出線各種常見(jiàn)關(guān)系的圖形,比如聚類(lèi)關(guān)系,線性關(guān)系,分布關(guān)系等:

In [120]: import numpy as np

In [121]: import matplotlib.pyplot as plt

In [122]: import seaborn as sns

In [123]: np.random.seed(sum(map(ord, "aesthetics")))

In [124]:

In [124]: def sinplot(flip=1):
     ...:     x = np.linspace(0, 14, 100)
     ...:     for i in range(1, 7):
     ...:         plt.plot(x, np.sin(x + i * .5) * (7 - i) * flip)
     ...:

In [125]: sns.set()

In [126]: sinplot()
In [127]: plt.show()

如下圖:


Figure_10.png

Bokeh 是一個(gè)現(xiàn)代化的繪圖工具,底層使用 D3.js 進(jìn)行繪圖,也就是說(shuō) Bokeh 繪制的圖形是基于瀏覽器顯示的,這也非常符合當(dāng)今的技術(shù)潮流,而且繪制的圖形交互功能更加強(qiáng)大。

In [131]: import numpy as np

In [132]: from bokeh.layouts import gridplot

In [133]: from bokeh.plotting import figure, show, output_file

In [134]: # sin曲線

In [135]: x = np.linspace(0, 4*np.pi, 100)

In [136]: y = np.sin(x)

In [137]: p = figure(title="Shiyanlou Bokeh Example")

In [138]: p.circle(x,  y, legend="sin(x)")
Out[138]: GlyphRenderer(id='9c2202a5-15c2-4282-b074-d3a964790ba7', ...)

In [139]: p.circle(x, 2*y, legend="2*sin(x)", color="orange")
Out[139]: GlyphRenderer(id='d3e000b9-c792-4321-a1a5-b51db3981841', ...)

In [140]: p.circle(x, 3*y, legend="3*sin(x)", color="green")
Out[140]: GlyphRenderer(id='ba52e19d-3238-463d-bfda-7dc9063fc070', ...)

In [141]: show(p)
bokeh_plot.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 一、概述 深度學(xué)習(xí)的一個(gè)重要手段是訓(xùn)練數(shù)據(jù)和訓(xùn)練過(guò)程的可視化,因此,我們關(guān)于深度學(xué)習(xí)的系列介紹文章就從Matplo...
    aoqingy閱讀 6,559評(píng)論 0 24
  • 申請(qǐng)季終于到了,準(zhǔn)留學(xué)生們又開(kāi)始了看最新一期排名選學(xué)校的季節(jié)。大家不要只顧著看那一字排開(kāi)的學(xué)校名稱,你們真的了解這...
    毛利大五郎_閱讀 972評(píng)論 0 0
  • 春回大地枝吐芽 生機(jī)盎然萬(wàn)物長(zhǎng) 重拾信心又出發(fā) 離家游子走天涯
    愛(ài)主愛(ài)人閱讀 283評(píng)論 0 0
  • 恰恰好的挫折,不會(huì)將一個(gè)人打擊到失去斗志,也不會(huì)讓他覺(jué)得無(wú)關(guān)痛癢,能讓其不斷去增強(qiáng)自體的能力,提升自己的內(nèi)聚力。任...
    423429d90f38閱讀 175評(píng)論 0 0
  • 開(kāi)心和悲傷一樣好玩,勇敢和恐懼都很刺激,經(jīng)歷了無(wú)奈無(wú)助才更能增加內(nèi)心力量。我們到這世界是來(lái)玩的!生命自身對(duì)完整的渴...
    shuangqq閱讀 462評(píng)論 0 0

友情鏈接更多精彩內(nèi)容