數據分析三劍客之Matplotlib


Matplotlib繪圖和可視化

簡介

我的前面兩篇文章介紹了 Nimpy ,Pandas 。今天來介紹一下Matplotlib。

簡單來說,Matplotlib 是 Python 的一個繪圖庫。它包含了大量的工具,你可以使用這些工具創建各種圖形,包括簡單的散點圖,正弦曲線,甚至是三維圖形。Python 科學計算社區經常使用它完成數據可視化的工作。

你可以在他們的網站上了解到更多 Matplotlib 背后的設計思想,但是我強烈建議你先瀏覽一下他們的圖庫,體會一下這個庫的各種神奇功能。

畫一個簡單的圖形

In [1]: import matplotlib.pyplot as plt

In [2]: import numpy as np

In [3]: x = np.linspace(0, 2 * np.pi, 50)

In [6]: plt.plot(x, np.sin(x))
Out[6]: [<matplotlib.lines.Line2D at 0x1dcdc98a748>]

In [7]: plt.show()

上面的代碼將畫出一個簡單的正弦曲線。np.linspace(0, 2 * np.pi, 50)這段代碼將會生成一個包含 50 個元素的數組,這 50 個元素均勻的分布在 [0, 2pi] 的區間上。

plot命令以一種簡潔優雅的方式創建了圖形。提醒一下,如果沒有第一個參數 x,圖形的 x 軸坐標將不再是 0 到 2pi,而應該是數組的索引范圍。

最后一行代碼 plt.show()將圖形顯示出來,如果沒有這行代碼圖像就不會顯示。

運行代碼后應該會類似得到下面的圖形:

在一張圖上繪制兩個數據集

大多數時候讀者可能更想在一張圖上繪制多個數據集。用 Matplotlib 也可以輕松實現這一點。

In [15]: x = np.linspace(0, 2 * np.pi, 50)

In [16]: plt.plot(x, np.sin(x), x, np.sin(2*x))
Out[16]:
[<matplotlib.lines.Line2D at 0x1dcdb38a080>,
 <matplotlib.lines.Line2D at 0x1dcdb38a1d0>]

In [17]: plt.show()

上面的代碼同時繪制了表示函數 sin(x) 和 sin(2x) 的圖形。這段代碼和前面繪制一個數據集的代碼幾乎完全相同,只有一點例外,這段代碼在調用plt.plot()的時候多傳入了一個數據集,並用逗號與第一個數據集分隔開。

最后你會得到類似於下面包含兩條曲線的圖形:

自定義圖形的外觀

當在同一個圖形上展示多個數據集時,通過改變線條的外觀來區分不同的數據集變得非常必要。

In [18]: x = np.linspace(0, 2*np.pi, 50)

In [19]: plt.plot(x, np.sin(x), 'r-o', x, np.cos(x), 'g--')
Out[19]:
[<matplotlib.lines.Line2D at 0x1dcdb695898>,
 <matplotlib.lines.Line2D at 0x1dcdb695a20>]

In [20]: plt.show()

上述代碼展示了兩種不同的曲線樣式:'r-o' 和 'g--'。字母 'r' 和 'g' 代表線條的顏色,后面的符號代表線和點標記的類型。例如 '-o' 代表包含實心點標記的實線,'--' 代表虛線。其他的參數需要讀者自己去嘗試,這也是學習 Matplotlib 最好的方式。

顏色: 藍色 - 'b' 綠色 - 'g' 紅色 - 'r' 青色 - 'c' 品紅 - 'm' 黃色 - 'y' 黑色 - 'k''b'代表藍色,所以這里用黑色的最后一個字母) 白色 - 'w' 線: 直線 - '-' 虛線 - '--' 點線 - ':' 點划線 - '-.' 常用點標記 點 - '.' 像素 - ',' 圓 - 'o' 方形 - 's' 三角形 - '^' 

更多點標記樣式點擊這里

最后你會得到類似下面的圖形:

使用子圖

使用子圖可以在一個窗口繪制多張圖。

In [21]: x = np.linspace(0, 2*np.pi, 50)

In [22]: plt.subplot(2, 1, 1)   # (行,列,活躍區)
Out[22]: <matplotlib.axes._subplots.AxesSubplot at 0x1dcdb6ba978>

In [23]: plt.plot(x, np.sin(x), 'r')
Out[23]: [<matplotlib.lines.Line2D at 0x1dcdb7316d8>]

In [24]: plt.subplot(2, 1, 2)
Out[24]: <matplotlib.axes._subplots.AxesSubplot at 0x1dcdb731ba8>

In [25]: plt.plot(x, np.cos(x), 'g')
Out[25]: [<matplotlib.lines.Line2D at 0x1dcdb77bfd0>]

In [26]: plt.show()

使用子圖只需要一個額外的步驟,就可以像前面的例子一樣繪制數據集。即在調用 plot() 函數之前需要先調用 subplot() 函數。該函數的第一個參數代表子圖的總行數,第二個參數代表子圖的總列數,第三個參數代表活躍區域。

活躍區域代表當前子圖所在繪圖區域,繪圖區域是按從左至右,從上至下的順序編號。例如在 4×4 的方格上,活躍區域 6 在方格上的坐標為 (2, 2)。

最終你會得到類似下面的圖形:

簡單的散點圖

散點圖是一堆離散點的集合。用 Matplotlib 畫散點圖也同樣非常簡單。

In [27]: x = np.linspace(0, 2*np.pi, 50)

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

In [29]: plt.scatter(x, y)
Out[29]: <matplotlib.collections.PathCollection at 0x1dcddb706a0>

In [30]: plt.show()

正如上面代碼所示,你只需要調用 scatter() 函數並傳入兩個分別代表 x 坐標和 y 坐標的數組。注意,我們通過 plot 命令並將線的樣式設置為 'bo' 也可以實現同樣的效果。

最后你會得到類似下面的無線圖形:

彩色映射散點圖

另一種你可能用到的圖形是彩色映射散點圖。這里我們會根據數據的大小給每個點賦予不同的顏色和大小,並在圖中添加一個顏色欄。

In [31]: x = np.random.rand(1000)

In [32]: y = np.random.rand(1000)

In [33]: size = np.random.rand(1000) * 50

In [34]: colour = np.random.rand(1000)

In [35]: plt.scatter(x, y, size, colour)
Out[35]: <matplotlib.collections.PathCollection at 0x1dcdde984e0>

In [36]: plt.colorbar()
Out[36]: <matplotlib.colorbar.Colorbar at 0x1dcddece0b8>

In [37]: plt.show()

上面的代碼大量的用到了 np.random.rand(1000),原因是我們繪圖的數據都是隨機產生的。

同前面一樣我們用到了 scatter() 函數,但是這次我們傳入了另外的兩個參數,分別為所繪點的大小和顏色。通過這種方式使得圖上點的大小和顏色根據數據的大小產生變化。

然后我們用 colorbar() 函數添加了一個顏色欄。

最后你會得到類似於下面的彩色散點圖:

直方圖

直方圖是另一種常見的圖形,也可以通過幾行代碼創建出來。

In [38]: x = np.random.randn(1000)

In [39]: plt.hist(x, 50)
Out[39]:
(array([ 2.,  0.,  0.,  1.,  2.,  2.,  1.,  0.,  1.,  1.,  9.,  6., 11.,
        16., 20., 18., 23., 26., 34., 25., 42., 31., 52., 40., 38., 56.,
        35., 49., 49., 41., 44., 46., 46., 31., 30., 32., 26., 24., 24.,
        16.,  8.,  5., 12.,  4.,  4.,  5.,  2.,  7.,  2.,  1.]),
 array([-3.32384545, -3.20164134, -3.07943724, -2.95723314, -2.83502904,
        -2.71282494, -2.59062084, -2.46841674, -2.34621264, -2.22400854,
        -2.10180443, -1.97960033, -1.85739623, -1.73519213, -1.61298803,
        -1.49078393, -1.36857983, -1.24637573, -1.12417163, -1.00196752,
        -0.87976342, -0.75755932, -0.63535522, -0.51315112, -0.39094702,
        -0.26874292, -0.14653882, -0.02433471,  0.09786939,  0.22007349,
         0.34227759,  0.46448169,  0.58668579,  0.70888989,  0.83109399,
         0.95329809,  1.0755022 ,  1.1977063 ,  1.3199104 ,  1.4421145 ,
         1.5643186 ,  1.6865227 ,  1.8087268 ,  1.9309309 ,  2.05313501,
         2.17533911,  2.29754321,  2.41974731,  2.54195141,  2.66415551,
         2.78635961]),
 <a list of 50 Patch objects>)

In [40]: plt.show()

直方圖是 Matplotlib 中最簡單的圖形之一。你只需要給 hist() 函數傳入一個包含數據的數組。第二個參數代表數據容器的個數。數據容器代表不同的值的間隔,並用來包含我們的數據。數據容器越多,圖形上的數據條就越多。

最終你會得到類似下面的直方圖:

標題,標簽和圖例

當需要快速創建圖形時,你可能不需要為圖形添加標簽。但是當構建需要展示的圖形時,你就需要添加標題,標簽和圖例。

In [41]: x = np.linspace(0, 2*np.pi, 50)

In [42]: plt.plot(x, np.sin(x), 'r-x', label='Sin(x)')
Out[42]: [<matplotlib.lines.Line2D at 0x1dcde55db00>]

In [43]: plt.plot(x, np.cos(x), 'g-^', label='Cos(x)')
Out[43]: [<matplotlib.lines.Line2D at 0x1dcde282ac8>]

In [44]: plt.legend()  # 展示圖例
Out[44]: <matplotlib.legend.Legend at 0x1dcde282dd8>

In [45]: plt.xlabel('Rads')  # 給x軸添加標簽
Out[45]: Text(0.5,0,'Rads')

In [46]: plt.ylabel('Amplitude')  # 給y軸添加標簽
Out[46]: Text(0,0.5,'Amplitude')

In [47]: plt.title('Sin and Cos Waves')  # 添加圖形標題
Out[47]: Text(0.5,1,'Sin and Cos Waves')

In [48]: plt.show()

為了給圖形添加圖例,我們需要在 plot() 函數中添加命名參數 'label' 並賦予該參數相應的標簽。然后調用 legend() 函數就會在我們的圖形中添加圖例。

接下來我們只需要調用函數 title()xlabel() 和 ylabel() 就可以為圖形添加標題和標簽。

你會得到類似於下面這張擁有標題、標簽和圖例的圖形:

餅圖

餅圖陰影、分裂等屬性設置:

# labels參數設置每一塊的標簽;

# labeldistance參數設置標簽距離圓心的距離(比例值)

# autopct參數設置比例值小數保留位(%.3f%%);

# pctdistance參數設置比例值文字距離圓心的距離

# explode參數設置每一塊頂點距圓心的長度(比例值,列表);

# colors參數設置每一塊的顏色(列表);

# shadow參數為布爾值,設置是否繪制陰影

# startangle參數設置餅圖起始角度

餅圖適合展示各部分占總體的比例,條形圖適合比較各部分的大小

In [51]: x = [11, 22, 33, 44]

In [52]: plt.pie(x, labels=['a', 'b', 'c', 'd'])
Out[52]:
([<matplotlib.patches.Wedge at 0x1dcde8894a8>,
  <matplotlib.patches.Wedge at 0x1dcde8899b0>,
  <matplotlib.patches.Wedge at 0x1dcde889e80>,
  <matplotlib.patches.Wedge at 0x1dcde891390>],
 [Text(1.04616,0.339919,'a'),
  Text(0.339919,1.04616,'b'),
  Text(-1.04616,0.339919,'c'),
  Text(0.339919,-1.04616,'d')])

In [53]: plt.show()

最終你會得到類似下面的餅圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM