Matplotlib
參考:[https://blog.csdn.net/qq_34859482/article/details/80617391]
Matplotlib 是Python中類似 MATLAB 的繪圖工具蝴簇,用于生成各類圖表腮猖。
import matplotlib.pyplot as plt
1. 認識Matploblib
Matplotlib基本圖表包括的元素有:
- x軸和y軸 axis
水平和垂直的軸線 - x軸和y軸刻度 tick
刻度標示坐標軸的分隔峻仇,包括最小刻度和最大刻度 - x軸和y軸刻度標簽 tick label
表示特定坐標軸的值 - 繪圖區(qū)域(坐標系) axes
- 坐標系標題 title
- 軸標簽 xlabel ylabel
1.1 Figure
建立一個Figure對象,即一張繪圖的畫板。
fig = plt.figure()
設置畫板的大小
fig = plt.figure(figsize=(4,2))
也可以繪圖完成后設置大小
將畫板分割成多個圖塊,建立子圖
plt.subplot(211)
plt.subplot(212)
以下寫法也是一樣的,用來建立子圖
ax1 = fig.add_subplot(211)
ax2 = fig.add_subplot(212)
1.2 Axes
在擁有Figure對象之后,在作畫前我們還需要軸贿肩,沒有軸的話就沒有繪圖基準,所以需要添加Axes龄寞。也可以理解成為真正可以作畫的紙汰规。
fig = plt.figure()
ax = fig.add_subplot(111)
ax.set(xlim=[0.5, 4.5], ylim=[-2, 8], title='An Example Axes',
ylabel='Y-Axis', xlabel='X-Axis')
plt.show()
上面的代碼,在一幅圖上添加了一個Axes物邑,然后設置了這個Axes的X軸以及Y軸的取值范圍(這些設置并不是強制的溜哮,后面會再談到關于這些設置)滔金,效果如下圖:
對于上面的fig.add_subplot(111)就是添加Axes的,參數的解釋的在畫板的第1行第1列的第一個位置生成一個Axes對象來準備作畫茂嗓。也可以通過fig.add_subplot(2, 2, 1)的方式生成Axes餐茵,前面兩個參數確定了面板的劃分,例如 2述吸, 2會將整個面板劃分成 2 * 2 的方格忿族,第三個參數取值范圍是 [1, 2*2] 表示第幾個Axes。如下面的例子:
fig = plt.figure()
ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(224)
1.3 Multiple Axes
可以發(fā)現我們上面添加 Axes 似乎有點弱雞蝌矛,所以提供了下面的方式一次性生成所有 Axes:
fig, axes = plt.subplots(nrows=2, ncols=2)
axes[0,0].set(title='Upper Left')
axes[0,1].set(title='Upper Right')
axes[1,0].set(title='Lower Left')
axes[1,1].set(title='Lower Right')
fig 還是我們熟悉的畫板道批, axes 成了我們常用二維數組的形式訪問,這在循環(huán)繪圖時入撒,額外好用隆豹。
1.4 Axes Vs .pyplot
相信不少人看過下面的代碼,很簡單并易懂茅逮,但是下面的作畫方式只適合簡單的繪圖璃赡,快速的將圖繪出。在處理復雜的繪圖工作時氮唯,我們還是需要使用 Axes 來完成作畫的鉴吹。
plt.plot([1, 2, 3, 4], [10, 20, 25, 30], color='lightblue', linewidth=3)
plt.xlim(0.5, 4.5)
plt.show()
2. 基本繪圖2D
2.1 線
plot()函數畫出一系列的點姨伟,并且用線將它們連接起來惩琉。看下例子:
x = np.linspace(0, np.pi)
y_sin = np.sin(x)
y_cos = np.cos(x)
ax1.plot(x, y_sin)
ax2.plot(x, y_sin, 'go--', linewidth=2, markersize=12)
ax3.plot(x, y_cos, color='red', marker='+', linestyle='dashed')
在上面的三個Axes上作畫夺荒。plot瞒渠,前面兩個參數為x軸、y軸數據技扼。ax2的第三個參數是 MATLAB風格的繪圖伍玖,對應ax3上的顏色,marker剿吻,線型窍箍。
另外,我們可以通過關鍵字參數的方式繪圖丽旅,如下例:
x = np.linspace(0, 10, 200)
data_obj = {'x': x,
'y1': 2 * x + 1,
'y2': 3 * x + 1.2,
'mean': 0.5 * x * np.cos(2*x) + 2.5 * x + 1.1}
fig, ax = plt.subplots()
#填充兩條線之間的顏色
ax.fill_between('x', 'y1', 'y2', color='yellow', data=data_obj)
# Plot the "centerline" with `plot`
ax.plot('x', 'mean', color='black', data=data_obj)
plt.show()
發(fā)現上面的作圖椰棘,在數據部分只傳入了字符串,這些字符串對一個這 data_obj 中的關鍵字榄笙,當以這種方式作畫時邪狞,將會在傳入給 data 中尋找對應關鍵字的數據來繪圖。
2.2 散點圖
只畫點茅撞,不用線連接起來帆卓。
x = np.arange(10)
y = np.random.randn(10)
plt.scatter(x, y, color='red', marker='+')
plt.show()
2.3 條形圖
條形圖分兩種巨朦,一種是水平的,一種是垂直的剑令,見下例子:
np.random.seed(1)
x = np.arange(5)
y = np.random.randn(5)
fig, axes = plt.subplots(ncols=2, figsize=plt.figaspect(1./2))
vert_bars = axes[0].bar(x, y, color='lightblue', align='center')
horiz_bars = axes[1].barh(x, y, color='lightblue', align='center')
#在水平或者垂直方向上畫線
axes[0].axhline(0, color='gray', linewidth=2)
axes[1].axvline(0, color='gray', linewidth=2)
plt.show()
條形圖還返回了一個Artists 數組糊啡,對應著每個條形,例如上圖 Artists 數組的大小為5吁津,我們可以通過這些 Artists 對條形圖的樣式進行更改悔橄,如下例:
fig, ax = plt.subplots()
vert_bars = ax.bar(x, y, color='lightblue', align='center')
# We could have also done this with two separate calls to `ax.bar` and numpy boolean indexing.
for bar, height in zip(vert_bars, y):
if height < 0:
bar.set(edgecolor='darkred', color='salmon', linewidth=3)
plt.show()
2.4 直方圖
直方圖用于統(tǒng)計數據出現的次數或者頻率,有多種參數可以調整腺毫,見下例:
np.random.seed(19680801)
n_bins = 10
x = np.random.randn(1000, 3)
fig, axes = plt.subplots(nrows=2, ncols=2)
ax0, ax1, ax2, ax3 = axes.flatten()
colors = ['red', 'tan', 'lime']
ax0.hist(x, n_bins, density=True, histtype='bar', color=colors, label=colors)
ax0.legend(prop={'size': 10})
ax0.set_title('bars with legend')
ax1.hist(x, n_bins, density=True, histtype='barstacked')
ax1.set_title('stacked bar')
ax2.hist(x, histtype='barstacked', rwidth=0.9)
ax3.hist(x[:, 0], rwidth=0.9)
ax3.set_title('different sample sizes')
fig.tight_layout()
plt.show()
參數中density控制Y軸是概率還是數量癣疟,與返回的第一個的變量對應。histtype控制著直方圖的樣式潮酒,默認是 ‘bar’睛挚,對于多個條形時就相鄰的方式呈現如子圖1, ‘barstacked’ 就是疊在一起急黎,如子圖2扎狱、3。 rwidth 控制著寬度勃教,這樣可以空出一些間隙淤击,比較圖2、3. 圖4是只有一條數據時故源。
2.5 餅圖
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
fig1, (ax1, ax2) = plt.subplots(2)
ax1.pie(sizes, labels=labels, autopct='%1.1f%%', shadow=True)
ax1.axis('equal')
ax2.pie(sizes, autopct='%1.2f%%', shadow=True, startangle=90, explode=explode,
pctdistance=1.12)
ax2.axis('equal')
ax2.legend(labels=labels, loc='upper right')
plt.show()
餅圖自動根據數據的百分比畫餅.污抬。labels是各個塊的標簽,如子圖一绳军。autopct=%1.1f%%表示格式化百分比精確輸出印机,explode,突出某些塊门驾,不同的值突出的效果不一樣射赛。pctdistance=1.12百分比距離圓心的距離,默認是0.6.
2.6 箱形圖
為了專注于如何畫圖奶是,省去數據的處理部分楣责。 data 的 shape 為 (n, ), data2 的 shape 為 (n, 3)聂沙。
fig, (ax1, ax2) = plt.subplots(2)
ax1.boxplot(data)
ax2.boxplot(data2, vert=False) #控制方向
2.7 泡泡圖
散點圖的一種秆麸,加入了第三個值 s 可以理解成普通散點,畫的是二維逐纬,泡泡圖體現了Z的大小蛔屹,如下例:
np.random.seed(19680801)
N = 50
x = np.random.rand(N)
y = np.random.rand(N)
colors = np.random.rand(N)
area = (30 * np.random.rand(N))**2 # 0 to 15 point radii
plt.scatter(x, y, s=area, c=colors, alpha=0.5)
plt.show()
2.8 等高線(輪廓圖)
有時候需要描繪邊界的時候,就會用到輪廓圖豁生,機器學習用的決策邊界也常用輪廓圖來繪畫兔毒,見下例:
fig, (ax1, ax2) = plt.subplots(2)
x = np.arange(-5, 5, 0.1)
y = np.arange(-5, 5, 0.1)
xx, yy = np.meshgrid(x, y, sparse=True)
z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2)
ax1.contourf(x, y, z)
ax2.contour(x, y, z)
上面畫了兩個一樣的輪廓圖漫贞,contourf會填充輪廓線之間的顏色。數據x, y, z通常是具有相同 shape 的二維矩陣育叁。x, y 可以為一維向量迅脐,但是必需有 z.shape = (y.n, x.n) ,這里 y.n 和 x.n 分別表示x豪嗽、y的長度谴蔑。Z通常表示的是距離X-Y平面的距離,傳入X龟梦、Y則是控制了繪制等高線的范圍隐锭。
3 布局、圖例說明计贰、邊界等
3.1區(qū)間上下限
當繪畫完成后钦睡,會發(fā)現X、Y軸的區(qū)間是會自動調整的躁倒,并不是跟我們傳入的X荞怒、Y軸數據中的最值相同。為了調整區(qū)間我們使用下面的方式:
ax.set_xlim([xmin, xmax]) #設置X軸的區(qū)間
ax.set_ylim([ymin, ymax]) #Y軸區(qū)間
ax.axis([xmin, xmax, ymin, ymax]) #X秧秉、Y軸區(qū)間
ax.set_ylim(bottom=-10) #Y軸下限
ax.set_xlim(right=25) #X軸上限
具體效果見下例:
x = np.linspace(0, 2*np.pi)
y = np.sin(x)
fig, (ax1, ax2) = plt.subplots(2)
ax1.plot(x, y)
ax2.plot(x, y)
ax2.set_xlim([-1, 6])
ax2.set_ylim([-1, 3])
plt.show()
可以看出修改了區(qū)間之后影響了圖片顯示的效果褐桌。
3.2 圖例說明
我們如果我們在一個Axes上做多次繪畫,那么可能出現分不清哪條線或點所代表的意思象迎。這個時間添加圖例說明荧嵌,就可以解決這個問題了,見下例:
fig, ax = plt.subplots()
ax.plot([1, 2, 3, 4], [10, 20, 25, 30], label='Philadelphia')
ax.plot([1, 2, 3, 4], [30, 23, 13, 4], label='Boston')
ax.scatter([1, 2, 3, 4], [20, 10, 30, 15], label='Point')
ax.set(ylabel='Temperature (deg C)', xlabel='Time', title='A tale of two cities')
ax.legend()
plt.show()
在繪圖時傳入 label 參數挖帘,并最后調用ax.legend()顯示體力說明完丽,對于 legend 還是傳入參數恋技,控制圖例說明顯示的位置:
Location String Location Code
‘best’ 0
‘upper right’ 1
‘upper left’ 2
‘lower left’ 3
‘lower right’ 4
‘right’ 5
‘center left’ 6
‘center right’ 7
‘lower center’ 8
‘upper center’ 9
‘center’ 10
3.3 區(qū)間分段
默認情況下拇舀,繪圖結束之后,Axes 會自動的控制區(qū)間的分段蜻底。見下例:
data = [('apples', 2), ('oranges', 3), ('peaches', 1)]
fruit, value = zip(*data)
fig, (ax1, ax2) = plt.subplots(2)
x = np.arange(len(fruit))
ax1.bar(x, value, align='center', color='gray')
ax2.bar(x, value, align='center', color='gray')
ax2.set(xticks=x, xticklabels=fruit)
#ax.tick_params(axis='y', direction='inout', length=10) #修改 ticks 的方向以及長度
plt.show()
上面不僅修改了X軸的區(qū)間段骄崩,并且修改了顯示的信息為文本。
3.4 布局
當我們繪畫多個子圖時薄辅,就會有一些美觀的問題存在要拂,例如子圖之間的間隔,子圖與畫板的外邊間距以及子圖的內邊距站楚,下面說明這個問題:
fig, axes = plt.subplots(2, 2, figsize=(9, 9))
fig.subplots_adjust(wspace=0.5, hspace=0.3,
left=0.125, right=0.9,
top=0.9, bottom=0.1)
#fig.tight_layout() #自動調整布局脱惰,使標題之間不重疊
plt.show()
通過fig.subplots_adjust()我們修改了子圖水平之間的間隔wspace=0.5,垂直方向上的間距hspace=0.3窿春,左邊距l(xiāng)eft=0.125 等等拉一,這里數值都是百分比的采盒。以 [0, 1] 為區(qū)間,選擇left蔚润、right磅氨、bottom、top 注意 top 和 right 是 0.9 表示上嫡纠、右邊距為百分之10烦租。不確定如果調整的時候,fig.tight_layout()是一個很好的選擇除盏。之前說到了內邊距叉橱,內邊距是子圖的,也就是 Axes 對象者蠕,所以這樣使用 ax.margins(x=0.1, y=0.1)赏迟,當值傳入一個值時,表示同時修改水平和垂直方向的內邊距蠢棱。
觀察上面的四個子圖锌杀,可以發(fā)現他們的X、Y的區(qū)間是一致的泻仙,而且這樣顯示并不美觀糕再,所以可以調整使他們使用一樣的X、Y軸:
fig, (ax1, ax2) = plt.subplots(1, 2, sharex=True, sharey=True)
ax1.plot([1, 2, 3, 4], [1, 2, 3, 4])
ax2.plot([3, 4, 5, 6], [6, 5, 4, 3])
plt.show()
3.5 軸相關
改變邊界的位置玉转,去掉四周的邊框:
fig, ax = plt.subplots()
ax.plot([-2, 2, 3, 4], [-10, 20, 25, 5])
ax.spines['top'].set_visible(False) #頂邊界不可見
ax.xaxis.set_ticks_position('bottom') # ticks 的位置為下方突想,分上下的。
ax.spines['right'].set_visible(False) #右邊界不可見
ax.yaxis.set_ticks_position('left')
# "outward"
# 移動左究抓、下邊界離 Axes 10 個距離
#ax.spines['bottom'].set_position(('outward', 10))
#ax.spines['left'].set_position(('outward', 10))
# "data"
# 移動左猾担、下邊界到 (0, 0) 處相交
ax.spines['bottom'].set_position(('data', 0))
ax.spines['left'].set_position(('data', 0))
# "axes"
# 移動邊界,按 Axes 的百分比位置
#ax.spines['bottom'].set_position(('axes', 0.75))
#ax.spines['left'].set_position(('axes', 0.3))
plt.show()