Matplotlib是一個可以將數據繪制為圖形表示的Python三方庫,包括線性圖(折線圖,函數圖)、柱形圖、餅圖等基礎而直觀的圖形,在平常的開發當中需要繪圖時就非常有用了。
安裝:pip install matplotlib或者下載安裝https://pypi.org/project/matplotlib/#files
demo效果圖:https://matplotlib.org/gallery.html,這里有許多效果圖,點擊對應的圖片就能看到源碼和生成的圖形,畫圖時可以看看這里有沒有自己想要的效果圖。
API文檔:Matplotlib的代碼是自文檔的,可以直接在源代碼中查看相關接口的文檔說明,或者使用Python的help()來進行查看。
Matplotlib教程:https://liam.page/2014/09/11/matplotlib-tutorial-zh-cn/,這篇筆記也是根據這個教程整理的,里面介紹的更加詳細,也有效果圖和對應代碼。
繪圖接口
import matplotlib:普通的繪圖使用from matplotlib import pyplot就行了,繪圖接口都在pyplot中,numpy也在pyplot中,使用from matplotlib.pyplot import np就行了(np就是numpy的別名,查看源碼可以看到:import numpy as np)。
import pylab:這個接口的語法和繪圖命令和Matlab相近,熟悉Matlab的可以選擇使用這個接口,numpy也可以直接從pylab中導入:from pylab import np(np就是numpy的別名,查看源碼可以看到:import numpy as np)。
numpy:這是一個用於數組運算的Python三方庫,安裝Matplotlib時會默認安裝這個庫,不會使用這個庫也沒關系,繪圖時直接使用Python的列表代替就行了,只是說使用numpy在某些情況下會方便些,比如繪制函數圖時。
線性圖
線性圖其實就是根據一系列X軸的點(列表數據)和對應的Y軸的點(列表數據),在圖上繪制出對應的點,每個點之間用線(實線、虛線等,默認是實線)連接起來,就形成了線性圖,所以無論是折線圖或者函數圖使用的接口都是一樣的。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 第一條線:一條普通的折線圖 x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x1, y1, color='red', linewidth=3, linestyle='--') # 第二條線:一條自定義的函數圖 x2 = np.array([1, 2, 3]) # y2其實就是x2的數組中每個元素進行運算(+0.5)后返回的新數組 y2 = x2 + 0.5 plt.plot(x2, y2) # 第三條線:一條sin函數圖 # linspace返回0到pi之間等間隔的200值組成的數組 x3 = np.linspace(0, np.pi, 200) # 返回x3中每個元素的sin值組成的數組 y3 = np.sin(x3) plt.plot(x3, y3) # 繪制並展示圖形 plt.show()
條形圖
條形圖與線性圖類似,也是根據x軸的點和y軸的點來進行繪制的,這時候y軸的點就代表了條形圖的高度了。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # arange和Python的range用法相同 x = np.arange(5) # uniform返回0到5之間(不包含5)的5個隨機數 y = np.random.uniform(0, 5, 5) # 繪制條形圖,facecolor設置背景色,edgecolor設置邊框顏色 plt.bar(x, y, facecolor='#9999ff', edgecolor='grey') # 將每個對應的y值顯示在條形圖上方 for x_, y_ in zip(x, y): plt.text(x_, y_, '{:.2f}'.format(y_), ha='center', va='bottom') # 繪制和顯示圖形 plt.show()
餅狀圖
餅圖的繪制需要給出一個數字的數組,如果數組中的數字的和小於1,那么餅圖中的每個區域就會以數組中的元素的數值大小來進行繪圖,不足1的那部分就會留作空白;如果數組中的數字的和大於等於1,那么就以每個元素的在數組和的占比來進行繪圖。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 如果數組的和小於1,則以元素自身大小作為餅圖占比,剩下的部分留作空白不繪制 # 如果數組的和大於等於1,則以元素在數組和的占比作為餅圖占比 areas = np.array([0.1, 0.4, 0.2, 0.1, 0.2]) # 每個區域距離相鄰區域的距離 explode = np.array([0, 0.1, 0, 0, 0]) # 在每個區域邊上的文本 labels = np.array(['one', 'two', 'three', 'four', 'five']) # autopct是在區域中顯示的各自百分比的格式 # startangle表示開始繪制的旋轉角度,90表示逆時針旋轉90度 plt.pie(areas, explode=explode, labels=labels, autopct='%1.1f%%', startangle=90) plt.show()
設置X軸和Y軸范圍
一般而言,X軸和Y軸的范圍會自動判斷和生成,但是因為X軸和Y軸的交點默認是各自的下限,並不是從0開始的,最后的繪制結果可能並不滿足自己的需求,所以可以自行設置,使之更加的符合自己的需求。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 一條普通的折線圖 x = np.array([1, 2, 3]) y = np.array([1, 2, 0.5]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x, y, color='red', linewidth=1, linestyle='--') # 設置X軸的范圍,上限和下限 plt.xlim(0, 5) # 設置Y中的范圍,上限和下限 plt.ylim(-1, 5) # 繪制並展示圖形 plt.show()
設置坐標軸記號和標簽
坐標軸默認的刻度記號顯示很多時候並不符合我們自己的需求,甚至有時候我們需要在指定的刻度記號處顯示特定的文本 ,但是如果自定義了顯示刻度記號,那圖上就只會顯示指定的記號,其他的默認刻度記號就不會再顯示了。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 一條普通的折線圖 x = np.array([1, 2, 3]) y = np.array([1, 2, 0.5]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x, y, color='red', linewidth=1, linestyle='--') # 設置X軸的范圍,上限和下限 plt.xlim(0, 5) # 設置Y中的范圍,上限和下限 plt.ylim(-1, 5) # 可以只設置記號,即只傳入第一個列表,且第一個列表的元素需要是在對應坐標軸的范圍內的值 # 如果傳入第二個列表,則第二個列表的元素內容(標簽)會替換第一個列表對應位置的記號 # 設置X軸的記號和標簽 plt.xticks([1, 3, 4, 5], [r'$x1$', r'$x3$', r'$x4$', r'$x5$']) # 設置Y軸的記號和標簽 plt.yticks([1, 2, 3, 5], [r'$y1$', r'$y2$', r'$y3$', r'$y5$']) # 繪制並展示圖形 plt.show()
添加第二個Y軸
有時候在繪制多個圖形時,不同的圖形使用的Y軸刻度不同,或者使用兩種不同的刻度顯示會更加直觀,這時候就可以左邊的Y軸使用一種刻度,右邊也添加一條Y軸,用於顯示另一種刻度,但注意的是它們共享X軸的刻度。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 第一條線:一條普通的折線圖 x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x1, y1, color='red', linewidth=3, linestyle='--') # 創建另一個坐標軸,此坐標軸與之前的坐標軸共用X軸,並將Y軸置於右邊 plt.twinx() # 第二條線:一條sin函數圖 # linspace返回0到pi之間等間隔的200值組成的數組 x2 = np.linspace(0, np.pi, 200) # 返回x2中每個元素的sin值組成的數組 y2 = np.sin(x2) plt.plot(x2, y2) # 繪制並展示圖形 plt.show()
移動坐標軸
橫縱坐標軸的交點位置默認在左下角,並且起點都是在各自的下限,但是有些時候我們希望交點位置在橫縱坐標的0點位置,也就是原點,這時候就可以移動坐標軸到我們想要的位置了。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 一條普通的折線圖 x = np.array([1, 2, 3]) y = np.array([1, 2, 0.5]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x, y, color='red', linewidth=1, linestyle='--') # 設置X軸的范圍,上限和下限 plt.xlim(-2, 5) # 設置Y中的范圍,上限和下限 plt.ylim(-2, 5) # 獲取當前的坐標軸對象 ax = plt.gca() # 設置右邊框和上邊框為無色 ax.spines['right'].set_color('none') ax.spines['top'].set_color('none') # 設置X軸的位置為下邊框的位置 ax.xaxis.set_ticks_position('bottom') # 設置下邊框的位置在Y軸0的位置,data表示Y軸數據,0為Y軸上的數據值 ax.spines['bottom'].set_position(('data', 0)) # 設置Y軸的位置為左邊框的位置 ax.yaxis.set_ticks_position('left') # 設置左邊框的位置在X軸0的位置,data表示X軸數據,0為X軸上的數據值 ax.spines['left'].set_position(('data', 0)) # 繪制並展示圖形 plt.show()
添加圖例
一般畫圖時,都需要為對應的圖形設置圖例,標明對應圖形的含義,不然圖形就不夠清晰明了了。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 第一條線:一條普通的折線圖 x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x1, y1, label='first line', color='red', linewidth=3, linestyle='--') # 第二條線:一條自定義的函數圖 x2 = np.array([1, 2, 3]) # y2其實就是x2的數組中每個元素進行運算(+0.5)后返回的新數組 y2 = x2 + 0.5 plt.plot(x2, y2, label='second line') # 第三條線:一條sin函數圖 # linspace返回0到pi之間等間隔的200值組成的數組 x3 = np.linspace(0, np.pi, 200) # 返回x3中每個元素的sin值組成的數組 y3 = np.sin(x3) plt.plot(x3, y3, label='third line') # 設置圖例,upper left表示左上角,loc參數的選項有: # best # upper right # upper left # lower left # lower right # right # center left # center right # lower center # upper center # center # 如果畫圖時沒有設置label參數或者不想使用label參數,可以給圖例重新設置label # 重新設置時,legend第一個參數傳入圖形列表,二個參數傳入對應的label列表,第三個參數就是loc了 plt.legend(loc='upper left') # 繪制並展示圖形 plt.show()
設置注釋
繪圖時,可能會需要給某些特殊的點注明一些說明性的注釋,以便更好的理解和分析圖形。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 一條自定義的函數圖 x = np.array([1, 2, 3]) # y2其實就是x2的數組中每個元素進行運算(+0.5)后返回的新數組 y = x + 0.5 plt.plot(x, y, label='first line') # 在指定位置顯示一個點 x_point = 2 y_point = x_point + 0.5 # scatter用於繪制散點圖,第一個參數和第二個參數列表中只有一個元素時自然就只畫一個點了 # 第三個參數用於指定繪制“點”的半徑 plt.scatter([x_point, ], [y_point, ], 10, color='red') # 給指定的點設置注釋 plt.annotate(r'2.5=2+0.5', # 注釋文本 xy=(x_point, y_point), # 點的位置 xycoords='data', xytext=(90, -50), # 以要注釋的點為原點,注釋文本的坐標位置(單位為像素) textcoords='offset points', arrowprops=dict(arrowstyle='->', connectionstyle='arc3, rad=.5')) # arc為直線,arc3為圓形,rad為半徑 # 繪制並展示圖形 plt.show()
繪制子圖
有時候我們可能需要在一張圖(figure)上同時繪制幾個或幾張圖形(subplot),以便更好的觀察和分析。
如果繪制圖形時沒有手動創建figure和子圖,Matplotlib自動創建一個figure和一個子圖,所有繪制出來的圖形直觀效果就是多個圖形都在同一個“圖片”上,且共用一個坐標軸。
多個figure,簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 第一個figure # num用於指定此figure的ID(int類型)或者指定此figure的標題 # figsize用於指定此figure的尺寸大小 plt.figure(num='My Figure Line', figsize=(6, 6)) # 一條普通的折線圖 x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x1, y1, label='first line', color='red', linewidth=3, linestyle='--') # 第二個figure # num用於指定此figure的ID(int類型)或者指定此figure的標題 # figsize用於指定此figure的尺寸大小 plt.figure(num=2, figsize=(5, 5)) # 一條sin函數圖 # linspace返回0到pi之間等間隔的200值組成的數組 x2 = np.linspace(0, np.pi, 200) # 返回x2中每個元素的sin值組成的數組 y2 = np.sin(x2) plt.plot(x2, y2, label='first line') plt.show()
同一個figure中繪制多個子圖,簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 創建一個figure,且創建一個2行1列的子圖網格,返回figure對象和子圖數組 # 網格默認為一行一列,此時返回子圖本身,如果網格只有一行或者一列,那就返回一個一維子圖數組,如果有多行多列,就返回對應的二維子圖數組 # subplots中傳入的參數可以是figure的參數 fig, axes = plt.subplots(2, 1, num='My Figure Demo') # 在第一個子圖中繪制一條普通的折線圖 x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 axes[0].plot(x1, y1, label='first line', color='red', linewidth=3, linestyle='--') # 顯示圖例 axes[0].legend() # 在第二個子圖中繪制一條sin函數圖 # linspace返回0到pi之間等間隔的200值組成的數組 x2 = np.linspace(0, np.pi, 200) # 返回x2中每個元素的sin值組成的數組 y2 = np.sin(x2) axes[1].plot(x2, y2, label='second line') # 顯示圖例 axes[1].legend() # 繪制並顯示 plt.show()
跨行或跨列繪制子圖,簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt from matplotlib import gridspec fig = plt.figure('My Figure Demo') grid = gridspec.GridSpec(2, 2, figure=fig) # 在第一行繪制一條普通的折線圖,占據一行的空間 axe1 = plt.subplot(grid[0, :]) x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 axe1.plot(x1, y1, label='first line', color='red', linewidth=3, linestyle='--') # 顯示圖例 axe1.legend() # 在第二行第一個子圖中繪制一條sin函數圖,在這里,以下三種表達都是相同的效果 # axe2 = plt.subplot(grid[1, :1]) # axe2 = plt.subplot(grid[1, :-1]) axe2 = plt.subplot(grid[1, 0]) # linspace返回0到pi之間等間隔的200值組成的數組 x2 = np.linspace(0, np.pi, 200) # 返回x2中每個元素的sin值組成的數組 y2 = np.sin(x2) axe2.plot(x2, y2, label='second line') # 顯示圖例 axe2.legend() # 繪制並顯示 plt.show()
顯示中文
Matplotlib默認是不只支持中文的,但是可以使用自帶的中文字體。
簡單示例:

# -*- coding:utf-8 -*- import numpy as np from matplotlib import pyplot as plt # 打印自帶的字體,可以從里面選一種中文字體 # from matplotlib import font_manager # for f in font_manager.fontManager.ttflist: # print(f.name) # 設置字體為SimHei(黑體) plt.rcParams['font.family'] = ['SimHei'] # 一條普通的折線圖 x1 = np.array([1, 2, 3]) y1 = np.array([1, 2, 3]) # linewidth設置線寬,單位為像素,linestyle默認為實線,“--”表示虛線 plt.plot(x1, y1, label='一條普通的折線圖', color='red', linewidth=3, linestyle='--') # 顯示圖例 plt.legend(loc='upper left') # 繪制並顯示 plt.show()
