官方網址:http://matplotlib.org/tutorials/introductory/lifecycle.html#sphx-glr-tutorials-introductory-lifecycle-py
根據官網描述,matplotlib有兩個接口:一個是(object-oriented interfacet)面向對象的接口,用於控制Figure和Axes,它控制一個或多個圖形的顯示;另一個是pyplot,它是MATLAB的封裝,每個Axes是一個依賴於pyplot的獨立子圖。
一、基本圖形的簡單用法
1、散點圖:最大的作用是查看兩個或多個數據的分布情況,可以查看數據的相關性(正相關,負相關),殘差分析等。
N = 1000 x = np.random.randn(N) y = np.random.randn(N) * 0.5 + x plt.scatter(y, x) plt.show()
N = 1000 x = np.random.rand(N);y = np.random.rand(N);colors = np.random.rand(N) area = np.pi * (15*np.random.rand(N)) ** 2 plt.scatter(x, y, s=area, c=colors, alpha=0.5) plt.show()
2、折線圖:用來描述數據隨時間的變化趨勢
數據文件https://files.cnblogs.com/files/kuaizifeng/test1data.zip
import time date, open_price, close_price = np.loadtxt('test1data.csv', delimiter=',', skiprows=1, usecols=(0, 1, 4), converters={0: lambda s:time.mktime(time.strptime(str(s, 'utf8'), '%Y/%m/%d'))}, unpack=True) plt.figure(figsize=(20 ,10)) plt.plot(date, open_price, color='green', marker='<') plt.plot(date, close_price, color='red', marker='>') # plt.xticks = [time.strftime('%Y/%m/%d', time.localtime(i)) for i in date] plt.show()
3、條形圖:用於不同分類數據的比較
N = 5 y = [20, 10, 30, 25, 15] index = np.arange(N) # plt.bar(left=index, height=y, color='red', width=0.5)#豎直方向 plt.bar(left=0, bottom=index, width=y, color='red', height=0.5, orientation='horizontal')# # left的是每個數組的左側坐標點,height是每個條形圖的數值 # 快速記憶:left,bottom;width,height是一一對應的關系 plt.show()
# 快速繪制 plt.barh(left=0, bottom=index, width=y) plt.show()
# 多個條形圖 index = np.arange(4) sales_BJ = [52, 55, 63, 53] sales_SH = [44, 66, 55, 41] bar_width = 0.3 plt.bar(left=index, height=sales_BJ, width=bar_width, color='b') plt.bar(left=index+bar_width, height=sales_SH, width=bar_width, color='r') plt.show()
# 堆積條形圖 index = np.arange(4) sales_BJ = [52, 55, 63, 53] sales_SH = [44, 66, 55, 41] bar_width = 0.3 plt.bar(left=index, height=sales_BJ, width=bar_width, color='b') plt.bar(left=index, bottom=sales_BJ, height=sales_SH, width=bar_width, color='r') plt.show()
# 橫向堆積條形圖 index = np.arange(4) sales_BJ = [52, 55, 63, 53] sales_SH = [44, 66, 55, 41] bar_width = 0.3 plt.barh(left=0, bottom=index, height=bar_width, width=sales_BJ, color='b') # 當然用orientation='horizontal'也是可以的 plt.barh(left=sales_BJ, bottom=index, height=bar_width, width=sales_SH, color='r') plt.show()
4、直方圖:有一系列高度不等的條形圖組成,用來表示連續型數據分布情況
# 正態分布直方圖 mean = 100# mean of distribution sigma = 20# standard of distribution x = mean + sigma*np.random.randn(10000) plt.hist(x, bins=50, color='green', normed=True) # bins:在直方圖里設置多少個條塊;normed:是否標准化;沒有標准化時縱坐標是‘個數’,標准化后縱坐標是‘頻率’ plt.show()
# 雙變量直方圖:用來探索雙變量的聯合分布情況 x = np.random.randn(1000) + 2 y = np.random.randn(1000) + 3 plt.hist2d(x, y, bins=40) plt.show()
5、餅狀圖:用來顯示一系列數據內各組數據的占比大小
labels = 'a', 'b', 'c', 'd' fracs = [15,30, 45, 10] # plt.axes(aspect=1)# 控制餅狀圖的比例:1表示正圓 plt.pie(x=fracs, labels=labels, autopct='%0.0f%%', explode=[0.1, 0., 0., 0.], shadow=True) # autopct:顯示比例;explode:每個餅塊里圓心的距離;添加陰影效果 plt.show()
6、箱線圖:用於顯示數據的集中和離散情況,以及檢測異常值
np.random.seed(100) data = np.random.normal(size=1000, loc=0, scale=1) plt.boxplot(data, sym='o', whis=1.5) # sym:用來調整異常值的形狀;whis:異常值的界限,默認是1.5倍四分位距 plt.show()
# 繪制多個箱線圖 np.random.seed(100) data = np.random.normal(size=(1000, 4), loc=0, scale=1) labels=['a', 'b', 'c', 'd'] plt.boxplot(data, labels=labels, sym='o', whis=1.5) plt.show()
二、元素樣式
# 八中內建顏色:blue、green、red、cyan、magenta、yellow、black、white;默認按這個順序畫多個圖形 # 其它顏色表示方法:灰色陰影、html十六進制、RGB元組 # 點的形狀23種 potstyle = ['.', ',', 'o', 'v', '^', '<', '>', '1', '2', '3', '4', '8', 's', 'p', '*', 'h', 'H', '+', 'X', 'D', 'd', '|', '-'] # 四種線型 linestyle = ['-', '--', '-.', ':'] # 樣式字符串就是三種樣式的簡寫方式,對應顏色、點、線型
# 示例 y = np.arange(1, 5) + 1 marker = ['b', 'g', 'r', 'c', 'm', 'y', 'b', 'w'] for i in range(8): plt.plot(y+i, marker[i]) plt.show()
y = np.arange(1, 5) plt.plot(y, color='g')#內置顏色 plt.plot(y+1, color='0.5')#回影顏色 plt.plot(y+2, color='#FF00FF')#十六進制表示法 plt.plot(y+3, color=(0.1, 0.2, 0.3))#RGB元組表示 plt.show()
y = np.arange(1, 5) plt.plot(y, marker='o')#指定marker時划線 plt.plot(y+1, 'D')#不指定marker時划點 plt.plot(y+2, '^') plt.plot(y+3, marker='p') plt.show()
# 樣式 y = np.arange(1, 5) plt.plot(y, 'cx--') plt.plot(y+1, 'kp:') plt.plot(y+2, 'mo-.') plt.show()
三、面向對象繪圖
三種繪圖方式:
1.pyplot:經典高層封裝;
2.pylab:將matplotlib和Numpy合並的模塊,模擬matplab的編程環境;不推薦使用,作者也不推薦使用;
3.面向對象的方式:matplotlib的精髓,更基礎和底層的方式.
1、畫布與子圖
figure對象是畫布,Axes對象是畫布里的子圖
# 繪制多個圖 fig1 = plt.figure() ax1 = fig1.add_subplot(111) ax1.plot([1, 2, 3], [3, 2, 1]) fig2 = plt.figure() ax2 = fig2.add_subplot(111) ax2.plot([1, 2, 3], [1, 2, 3]) plt.show()
# 一張圖里放多個子圖 x = np.arange(1, 100) fig = plt.figure() ax1 = fig.add_subplot(221);ax1.plot(x, x)# plt.subplot(221) ax2 = fig.add_subplot(222);ax2.plot(x, -x) ax3 = fig.add_subplot(223);ax3.plot(-x, x) ax4 = fig.add_subplot(224);ax4.plot(-x, -x) plt.show()
2、網格線
y = np.arange(1, 10) plt.plot(y, y**2) plt.grid(color='r', linewidth='0.5', linestyle=':')#網格 plt.show()
3、圖例
x = np.arange(1, 11, 1) plt.plot(x, x**2, label='Normal')#在圖形中寫上線的標簽 plt.plot(x, x**3, label='Fast') plt.plot(x, x**4, label='Fastest') plt.legend(loc=1, ncol=3) #1,2,3,4表示右上、左上、左下、右下.0表示自動.ncol表示幾列. plt.show()
x = np.arange(1, 11, 1) plt.plot(x, x**2, label='Normal')#在圖形中寫上線的標簽 plt.plot(x, x**3, label='Fast') plt.plot(x, x**4, label='Fastest') plt.legend(['Normal', 'Fast', 'Fastest'], loc='upper right') #1,2,3,4表示右上、左上、左下、右下.0表示自動.ncol表示幾列. plt.show()
x = np.arange(1, 11, 1) fig = plt.figure();ax = fig.add_subplot(111); l, = plt.plot(x, x**2);l.set_label('Normal set')#設置label ax.legend(loc=1)#注意這里的ax plt.show()
4、坐標軸
# 設置坐標軸范圍 x = np.arange(-10, 11, 1) fig = plt.figure();ax = fig.add_subplot(111); ax.plot(x, x*x) print(ax.axis())#[-11, 11, -5, 105]表示的是x的最小和最大值、y的最小和最大值 ax.axis([-5, 5, 0, 25])#設置坐標軸范圍方式 plt.show()
# 設置坐標軸范圍 x = np.arange(-10, 11, 1) fig = plt.figure();ax = fig.add_subplot(111); ax.plot(x, x*x) ax.set_xlim([-5, 5])#以列表的方式些參數 ax.set_ylim(ymin=-5, ymax=50)#以關鍵字參數的方式寫參數 plt.show()
# 添加坐標軸 x = np.arange(2, 20, 1) y1 = x*x;y2 = np.log(x) plt.plot(x, y1) plt.twinx()#添加x坐標軸,默認是0到1 plt.plot(x, y2, 'r')#第二條線就直接畫在twinx上了? plt.show()
# 添加坐標軸 x = np.arange(2, 20, 1) y1 = x*x;y2 = np.log(x) fig = plt.figure(); ax1 = fig.add_subplot(111) ax1.plot(x, y1);ax1.set_ylabel('Y1') ax2 = ax1.twinx(); #實例化一個子圖ax1,添加坐標軸是這個子圖的一個方法 ax2.plot(x, y2, 'r');ax2.set_ylabel('Y2') ax1.set_xlabel('Compare Y1 and Y2') plt.show() # 當然,有twinx(),就有twiny()
5、注釋
# 添加注釋:為了給某個數據添加強調效果 x = np.arange(-10, 11, 1) plt.plot(x, x*x) plt.annotate('this is the bottom', xy=(0,1), xytext=(0,20), arrowprops=dict(facecolor='c', width=50, headlength=10, headwidth=30))# 文本內容;箭頭坐標;文本內容坐標;箭頭設置: plt.show()
# 純文字標注 x = np.arange(-10, 11, 1) plt.plot(x, x*x) plt.text(-4.5, 40, 'function:y=x*x', family='serif', size=20, color='r') plt.text(-4, 20, 'function:y=x*x', family='fantasy', size=20, color='g') plt.text(-4, 60, 'fuction:y=x*x', size=20, style='italic', weight=1000, bbox=dict(facecolor='g'), rotation=30) #style:italic和oblique都是斜體;weight是粗細0-1000,或者寫名稱 # bbox給text加上邊緣效果設置,還有其它的參數;text還有水平線、豎直線等等;arrowprops也還有其它的效果參數 plt.show()
6、數學公式
matplotlib自帶mathtext引擎,遵循Latex排版規范。$作為開頭和結束符,如"$ y=x**2 $";特殊表達式和字符前面要加"\";公式里的參數設置,要以{}括起來。
fig = plt.figure();ax = fig.add_subplot(111); ax.set_xlim([1, 7]) ax.set_ylim([1, 5]) ax.text(2, 4, r'$ \alpha_i \beta \pi \lambda \omega $', size=20) # 下標用_i ax.text(4, 4, r'$ \sin(x) = \cos(\frac{\pi}{2}) $', size=20) # \frac{}{},分式:分子/分母 ax.text(2, 2, r'$ \lim_{x \rightarrow y} (\frac{1}{x^3}) $', size=20) ax.text(4, 2, r'$ \sqrt[4]{4x}{4x} = \sqrt{y} $', size=20) # sqrt開方的參數是[] plt.show()
四、區域填充
1、fill和fill_between
x = np.linspace(0, 5*np.pi, 1000);y1 = np.sin(x); y2 = np.sin(2*x) # plt.plot(x, y1); plt.plot(x, y2) # 不寫plot,是因為它畫了線 plt.fill(x, y1, 'b', alpha=0.3);plt.fill(x, y2, 'r', alpha=0.3)#填充的是圖形與x軸之間的區域 plt.show()
x = np.linspace(0, 5*np.pi, 1000);y1 = np.sin(x); y2 = np.sin(2*x) fig = plt.figure();ax = fig.add_subplot(111) ax.plot(x, y1, 'r', x, y2, 'b') ax.fill_between(x, y1, y2, facecolor='yellow', interpolate=True) ax.fill_between(x, y1, y2, where=y1>y2, facecolor='green', interpolate=True) # 放大時會出現空白,interpolate是把空白填上 plt.show()
2、patches:補丁
import matplotlib.patches as mpatches fig, ax = plt.subplots() # 圓形 xy1 = np.array([0.2, 0.2]) circle = mpatches.Circle(xy1, 0.05)#第一個參數是xy1圓心,第二個參數是半徑 ax.add_patch(circle) # 長方形 xy2 = np.array([0.2, 0.8]) rect = mpatches.Rectangle(xy2, 0.2, 0.1, color='r')#第一個參數是矩形右下角,第二個和第三個參數是寬和高 ax.add_patch(rect) # 多邊形 xy3 = np.array([0.8, 0.2]) polygon = mpatches.RegularPolygon(xy3, 6, 0.1, color='g')#多邊形中心、邊數、半徑 ax.add_patch(polygon) # 橢圓 xy4 = np.array([0.8, 0.8]) ellipse = mpatches.Ellipse(xy4, 0.4, 0.2, color='y') ax.add_patch(ellipse) plt.axis('equal')#調整x,y的顯示比例 plt.grid() plt.show() # 還有其它的圖形,參考matplotlib官網的patches模塊說明
五、繪圖樣式
def plot(style): fig, axes = plt.subplots(ncols=2, nrows=2) ax1, ax2, ax3, ax4 = axes.ravel() # 選擇繪圖樣式 plt.style.use(style) # 第一張圖 x, y = np.random.normal(size=(2, 100)) ax1.plot(x, y, 'o') # 第二張圖 x = np.arange(0, 10);y = np.arange(0, 10) ncolors = len(plt.rcParams['axes.prop_cycle']) # plt.rcParams['axes.prop_cycle'] #默認是七種顏色 shift = np.linspace(0, 10, ncolors) for s in shift: ax2.plot(x, y+s, '-') # 第三張圖 x = np.arange(5) y1, y2, y3 = np.random.randint(1, 25, size=(3,5)) width=0.25 ax3.bar(x, y1, width); ax3.bar(x+width, y2, width, color=list(plt.rcParams['axes.prop_cycle'])[1]['color']) ax3.bar(x+2*width, y3, width, color=list(plt.rcParams['axes.prop_cycle'])[2]['color']) # 第四張圖 for i in list(plt.rcParams['axes.prop_cycle']): xy = np.random.normal(size=2) ax4.add_patch(plt.Circle(xy, radius=0.3, color=i['color'])) ax4.axis('equal') plt.show() # 注:plt.rcParams['axes.prop_cycle']是一個七種顏色的迭代器 # list之后是[{'color':'#ff7f0e', ... },...],再根據位置和鍵'color'取值
# print(plt.style.available)# 23種樣式可供選擇 plot(style='dark_background') plot(style='ggplot') plot(style='fivethirtyeight')
六、極坐標繪制
r = np.arange(1, 6, 1) theta = [0, np.pi/2, np.pi, np.pi*3/2, 2*np.pi] ax = plt.subplot(111, projection='polar')# 投影到極坐標 ax.plot(theta, r, color='r', linewidth=3) plt.show()
r = np.empty(5) r.fill(5) theta = [0, np.pi/2, np.pi, np.pi*3/2, 2*np.pi] ax = plt.subplot(111, projection='polar') ax.plot(theta, r, color='r', linewidth=3) plt.show()
r = [10.0, 8.0, 6.0, 8.0, 9.0, 5.0, 9.0] theta = [(np.pi*2/6)*i for i in range(7)] ax = plt.subplot(111, projection='polar') bars = ax.bar(theta, r, linewidth=2) for color, bar in zip(list(plt.rcParams['axes.prop_cycle']), bars): bar.set_facecolor(color['color']) bar.set_alpha(0.7) ax.set_theta_direction(1)#方向,1表示順時針,2表示逆時針 ax.set_theta_zero_location('N')#極坐標0位置,默認是橫坐標,可設置八個方向N,NW,W,SW,S,SE,E,NE ax.set_thetagrids(np.arange(0.0, 360.0, 30.0))#外圈網格線刻度 ax.set_rgrids(np.arange(1.0, 10.0, 1.0))#內網格線虛線數 ax.set_rlabel_position('0')#內網格線坐標標簽的位置,相對於0坐標軸 plt.show()
七、綜合練習
1、積分圖形
def func(x): return -(x-2)*(x-8) + 40 x = np.linspace(0, 10) y = func(x) fig, ax = plt.subplots() plt.style.use('ggplot') plt.plot(x, y, 'r', linewidth=1) # 添加a, b a, b =2, 9 ax.set_xticks([a, b]) ax.set_yticks([]) ax.set_xticklabels([r'$a$', r'$b$']) # 添加坐標標簽 plt.figtext(0.9, 0.02, r'$x$') plt.figtext(0.05, 0.9, r'$y$') # 設置N*2的array,用Polygon包起來 ix = np.linspace(a, b);iy = func(ix);ixy = zip(ix, iy) verts=[(a, 0)] + list(ixy) + [(b, 0)] from matplotlib.patches import Polygon poly = Polygon(verts, facecolor='0.9', edgecolor='0.1')#'0.9'表示默認是灰色的,調整灰色程度 ax.add_patch(poly) x_math=(a+b)*0.5;y_math=35 plt.text(x_math, y_math, r'$ \int_a^b (-(x-2)*(x-8) + 40) dx $', fontsize=20, horizontalalignment='center') ax.set_ylim([25, 50]) plt.show()
2、散點和條形圖
x = np.random.randn(200);y = x+np.random.randn(200)*1.0 #left, bottom, width, height ax1 = plt.axes([0.1, 0.1, 0.6, 0.6]) ax2 = plt.axes([0.1, 0.1+0.6+0.02, 0.6, 0.2]) ax3 = plt.axes([0.1+0.6+0.02, 0.1, 0.2, 0.6]) ax2.set_xticks([]) ax3.set_yticks([]) xymax = np.max([np.max(np.fabs(x)), np.max(np.fabs(y))]) ax1.scatter(x, y) bin_width = 0.25 lim = np.ceil(xymax/bin_width) * bin_width bins = np.arange(-lim, lim, bin_width) ax2.hist(x, bins=bins) ax3.hist(y, bins=bins, orientation='horizontal') ax2.set_xlim(ax2.get_xlim()) ax3.set_ylim(ax3.get_ylim()) plt.show()
3、雷達圖
from matplotlib.font_manager import FontProperties font = FontProperties(fname=r'c:/Windows/Fonts/simsun.ttc', size=18) plt.style.use('ggplot') ax1 = plt.subplot(221, projection='polar') ax2 = plt.subplot(222, projection='polar') ax3 = plt.subplot(223, projection='polar') ax4 = plt.subplot(224, projection='polar') ability = ['進攻', '防守', '盤帶', '速度', '體力', '射術'] playerName = ['M', 'H', 'P', "Q"] playerData = {} for i in range(4): data = list(np.random.randint(size=6, low=60, high=99)) l = [j for j in data];l.append(data[0]) playerData[playerName[i]] = l theta = [(2*np.pi/6)*i for i in range(7)] ax1.plot(theta, playerData['M'], 'r') ax1.fill(theta, playerData['M'], 'r', alpha=0.2) ax1.set_xticks(theta) ax1.set_xticklabels(ability, FontProperties=font, y=0.3) ax1.set_title('梅西', position=(0.5, 0.4), FontProperties=font) ax1.set_yticks([60, 80, 100]) ax2.plot(theta, playerData['H'], 'g') ax2.fill(theta, playerData['H'], 'g', alpha=0.2) ax2.set_xticks(theta) ax2.set_xticklabels(ability, FontProperties=font, y=0.3) ax2.set_title('哈維', position=(0.5, 0.4), FontProperties=font) ax3.plot(theta, playerData['P'], 'b') ax3.fill(theta, playerData['P'], 'b', alpha=0.2) ax3.set_xticks(theta) ax3.set_xticklabels(ability, FontProperties=font, y=0.3) ax3.set_title('皮克', position=(0.5, 0.4), FontProperties=font) ax4.plot(theta, playerData['Q'], 'y') ax4.fill(theta, playerData['Q'], 'y', alpha=0.2) ax4.set_xticks(theta) ax4.set_xticklabels(ability, FontProperties=font, y=0.3) ax4.set_title('切赫', position=(0.5, 0.4), FontProperties=font) plt.show()
4、函數曲線
Figure的幾個參數:
num 圖形
figsize 尺寸
dpi 每英寸點數分辨率
facecolor 繪畫背景顏色
edgecolor 繪制背景周圍的邊緣顏色
frameon 是否繪制圖形框
import numpy as np import matplotlib.pyplot as plt plt.figure(figsize=(10,6),dpi=80) X = np.linspace(-np.pi,np.pi,256,endpoint=True) C,S = np.cos(X),np.sin(X) #設置數據線 plt.plot(X,C,color='blue',lw=2.5,ls='-',label='cosine')#設置數據線 plt.plot(X,S,color='red',lw=2.5,ls='-',label='sine') # plt.xlim(X.min()*1.1,X.max()*1.1)#這里一直報錯,不知道為什么 # plt.ylim(C.min()*1.1,X.max()*1.1) #設置坐標刻度和刻度標簽 # plt.xticks([-np.pi,-np.pi/2,0,np.pi/2,np.pi]) #設置x,y坐標 # plt.yticks([-1,0,+1]) plt.xticks([-np.pi,-np.pi/2,0,np.pi/2,np.pi],[r'$-\pi$',r'$-\pi/2$',r'$0$',r'$+\pi/2$',r'$+\pi$']) plt.yticks([-1,0,+1],[r'$-1$',r'$0$',r'$+1$']) #設置坐標軸 ax = plt.gca() #gca是用來回去當前axes(坐標圖)和修改權限:get current axes(handle) ax.spines['top'].set_color('none') #設置上、右脊骨(數據框) ax.spines['right'].set_color('None') ax.spines['left'].set_position(('data',0)) #左、下數據軸,(data’,0)表示以原坐標軸為軸,以0為中心點 ax.spines['bottom'].set_position(('data',0)) ax.yaxis.set_ticks_position('left') #這兩個才是設置坐標軸,但是在這里刪掉都可以 ax.xaxis.set_ticks_position('bottom') #設置圖例 plt.legend(loc='upper left',frameon=False)#需在plt.plot中設置label #設置注釋 t = 2*np.pi/3 # t1 = np.sin(t) plt.scatter([t,],[np.sin(t),],50,color='red') #設置注釋點位置、顏色 plt.plot([t,t],[0,np.sin(t)],color="red",linewidth=1.5,linestyle="--") #設置兩條虛線 plt.plot([0,t],[np.sin(t),np.sin(t)],color="red",linewidth=1.5,linestyle="--") plt.annotate(r'$\sin(\frac{2\pi}{3})=\frac{\sqrt{3}}{2}$', xy=(t,np.sin(t)),xycoords='data',xytext=(+10,+50), textcoords='offset points',fontsize=16, arrowprops=dict(arrowstyle='->',connectionstyle='arc3,rad=.2')) #設置注釋 plt.scatter([t,],[np.cos(t),],50,color='blue') plt.plot([t,t],[0,np.cos(t)],color='blue',linewidth=1.5,linestyle='--') plt.plot([0,t],[np.cos(t),np.cos(t)],color='blue',lw=1.5,ls='--') plt.annotate(r'$\cos(\frac{2\pi}{3})=-\frac{1}{2}$', xy=(t,np.cos(t)),xycoords='data',xytext=(-90,-50), textcoords='offset points',fontsize=16, arrowprops=dict(arrowstyle='->',connectionstyle='arc3,rad=.2')) #設置坐標軸和數據線重合處的顯示 for label in ax.get_xticklabels()+ax.get_yticklabels(): label.set_fontsize(16) label.set_bbox(dict(facecolor='white',edgecolor='None',alpha=0.65)) #保存圖形 # plt.savefig('.../figures/subplot-horizontal.png',dpi=64) plt.show()