matplotlib - 2D 與 3D 圖的繪製(上)


一、類MATLAB API

from pylab import *
%matplotlib qt              #使用 qt 作爲圖形後端

例:

from pylab import *
from numpy import *
x = linspace(0, 5, 10)
y = x ** 2

figure()
plot(x, y, 'r')
xlabel('x')
ylabel('y')
title('title')
show()

這裏寫圖片描述

創建子圖,選擇繪圖用的顏色與描點符號:

subplot(1,2,1)
plot(x, y, 'r--')
subplot(1,2,2)
plot(y, x, 'g*-');

這裏寫圖片描述

此類 API 的好處是可以節省代碼量,但處理複雜圖表時, matplotlib 面向對象 API 是一個更好的選擇。

二、matplotlib 面向對象 API

import matplotlib.pyplot as plt

這種方法不創建一個全局實例,而是將新建實例的引用保存在 fig 變量中,如果想在圖中新建一個座標軸實例,只需要調用 fig 實例的 add_axes 方法:
對上上例二次函數的繪製改爲:

fig = plt.figure()

axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # left, bottom, width, height (range 0 to 1)
#如果不在意座標軸在圖中的排放位置️,可以使用matplotlib的佈局管理器如subplots 則上兩句可改爲:
#   fig, axes = plt.subplots()
axes.plot(x, y, 'r')

axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('title')

fig

這樣對於圖表的繪製有了完全的控制權,可以很容易地多加一個座標軸到圖中:

fig = plt.figure()

axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # main axes
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # inset axes

# main figure
axes1.plot(x, y, 'r')
axes1.set_xlabel('x')
axes1.set_ylabel('y')
axes1.set_title('title')

# insert
axes2.plot(y, x, 'g')
axes2.set_xlabel('y')
axes2.set_ylabel('x')
axes2.set_title('insert title');

這裏寫圖片描述

subplots佈局管理器用法舉例:

fig, axes = plt.subplots(nrows=1, ncols=2)

for ax in axes:
    ax.plot(x, y, 'r')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('title')

fig.tight_layout() #若標籤重疊可使用 fig.tight_layout 自動調整標籤的位置
fig

這裏寫圖片描述

圖表尺寸,長寬比 與 DPI

在創建 Figure 對象的時候,使用figsize 與 dpi 參數能夠設置圖表尺寸與DPI, 創建一個800*400像素,每英寸100像素的圖如下:

fig = plt.figure(figsize=(8,4), dpi=100)

=><matplotlib.figure.Figure at 0x7f29c2b47990>

用在佈局管理器上:

fig, axes = plt.subplots(figsize=(12,3))

保存圖表

savefig 用於保存圖表:

fig.savefig("filename.png")
fig.savefig("filename.png", dpi=200)   #可以有選擇地指定DPI,並且選擇不同的輸出格式

Matplotlib 可以生成多種格式的高質量圖像,包括PNG,JPG,EPS,SVG,PGF 和 PDF。如果是科學論文的話儘量使用pdf格式。 (pdflatex 編譯的 LaTeX 文檔使用 includegraphics 命令就能包含 PDF 文件)。 一些情況下,PGF也是一個很好的選擇。

圖例,軸標 與 標題

set_title:給座標軸實例加上標題:

ax.set_title(“title”)

set_xlabelset_ylabel:設置座標x軸與y軸的標籤:

ax.set_xlabel(“x”)
ax.set_ylabel(“y”)

有兩種方法在圖中加入圖例。一種是調用座標軸對象的 legend 方法,傳入與之前定義的幾條曲線相對應的圖例文字的 列表/元組:

ax.legend([“curve1”, “curve2”, “curve3”])

這種方式容易出錯,比如增加了新的曲線或者移除了某條曲線。更好的方式是在調用 plot方法時使用 label=”label text” 參數,再調用 legend 方法加入圖例:

ax.plot(x, x**2, label="curve1")
ax.plot(x, x**3, label="curve2")
ax.legend();

legend 還有一個可選參數 loc 決定畫出圖例的位置,最常用的值如下:

ax.legend(loc=0) # let matplotlib decide the optimal location
ax.legend(loc=1) # upper right corner
ax.legend(loc=2) # upper left corner
ax.legend(loc=3) # lower left corner
ax.legend(loc=4) # lower right corner
# .. many more options are available

=> <matplotlib.legend.Legend at 0x4c863d0>

標題,軸標,與圖例的用法例子:

import matplotlib.pyplot as plt
from numpy import *
x = linspace(0, 5, 10)
fig, ax = plt.subplots()

ax.plot(x, x**2, label="y = x**2")
ax.plot(x, x**3, label="y = x**3")
ax.legend(loc=2); # upper left corner
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('title');

fig

這裏寫圖片描述

格式化文本,LaTeX,字體大小,字體類型

Matplotlib 對 LaTeX 提供了很好的支持。只需要將 LaTeX 表達式封裝在 美元符號 內,就可以在圖的任何文本中顯示了,比如 “$y=x^3$”

在 LaTeX 中常常會用到反斜槓,比如 \alpha 來產生符號 $\alpha$ 。但反斜槓在 python 字符串中是有特殊含義的, 爲了不出錯需要使用原始文本,只需要在字符串的前面加個r就行了,像是 r”\alpha” 或者 r’\alpha’:

# Update the matplotlib configuration parameters:

#from matplotlib import rcParams
#rcParams.update({'font.size': 18, 'font.family': 'serif'}) / rcParams.update({'font.size': 18, 'font.family': 'STIXGeneral', 'mathtext.fontset': 'stix'})
#若需要更改全局字體大小或者類型則加上上兩行,STIX 字體是一種好選擇

#rcParams.update({'font.size': 18, 'text.usetex': True})
#也可以將圖中的文本全用 Latex 渲染

# 重置
#matplotlib.rcParams.update({'font.size': 12, 'font.family': 'sans', 'text.usetex': False})

fig, ax = plt.subplots()

ax.plot(x, x**2, label=r"$y = \alpha^2$")
ax.plot(x, x**3, label=r"$y = \alpha^3$")
ax.legend(loc=2) # upper left corner
ax.set_xlabel(r'$\alpha$', fontsize=18)
ax.set_ylabel(r'$y$', fontsize=18)
ax.set_title('title');

fig

這裏寫圖片描述

設置顏色,線寬 與 線型

有很多方法定義線的顏色和其他圖形元素。首先,可以使用類MATLAB語法,’b’ 代表藍色,’g’ 代表綠色,依此類推。matplotlib同時也支持 MATLAB API 選擇線型所使用的方式, 比如 ‘b.-’ 意味着藍線標着點:

# MATLAB style line color and style 
ax.plot(x, x**2, 'b.-') # blue line with dots
ax.plot(x, x**3, 'g--') # green dashed line

fig

也可以顏色的名字或者RGB值選擇顏色,alpha參數決定了顏色的透明度:

fig, ax = plt.subplots()

ax.plot(x, x+1, color="red", alpha=0.5) # half-transparant red
ax.plot(x, x+2, color="#1155dd")        # RGB hex code for a bluish color
ax.plot(x, x+3, color="#15cc55")        # RGB hex code for a greenish color

fig

linewidth 或是 lw 參數改變線寬。 linestyle 或是 ls 參數改變線的風格。

fig, ax = plt.subplots(figsize=(12,6))

ax.plot(x, x+1, color="blue", linewidth=0.25)
ax.plot(x, x+2, color="blue", linewidth=0.50)
ax.plot(x, x+3, color="blue", linewidth=1.00)
ax.plot(x, x+4, color="blue", linewidth=2.00)

# possible linestype options ‘-‘, ‘–’, ‘-.’, ‘:’, ‘steps’
ax.plot(x, x+5, color="red", lw=2, linestyle='-')
ax.plot(x, x+6, color="red", lw=2, ls='-.')
ax.plot(x, x+7, color="red", lw=2, ls=':')

# custom dash
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10]) # format: line length, space length, ...

# possible marker symbols: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
ax.plot(x, x+ 9, color="green", lw=2, ls='-', marker='+')
ax.plot(x, x+10, color="green", lw=2, ls='-', marker='o')
ax.plot(x, x+11, color="green", lw=2, ls='-', marker='s')
ax.plot(x, x+12, color="green", lw=2, ls='-', marker='1')

# marker size and color
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+16, color="purple", lw=1, ls='-', marker='s', markersize=8, 
        markerfacecolor="yellow", markeredgewidth=2, markeredgecolor="blue")

fig

這裏寫圖片描述

控制座標軸的樣式

座標軸的範圍可以使用 set_ylim 或是 set_xlim 方法或者 axis(‘tight’) 自動將座標軸調整的緊湊 :

fig, axes = plt.subplots(1, 3, figsize=(12, 4))

axes[0].plot(x, x**2, x, x**3)
axes[0].set_title("default axes ranges")

axes[1].plot(x, x**2, x, x**3)
axes[1].axis('tight')
axes[1].set_title("tight axes")

axes[2].plot(x, x**2, x, x**3)
axes[2].set_ylim([0, 60])
axes[2].set_xlim([2, 5])
axes[2].set_title("custom axes range");

fig

這裏寫圖片描述
也可以將軸的刻度設置成對數刻度,調用 set_xscale 與 set_yscale 設置刻度,參數選擇 “log” :

fig, axes = plt.subplots(1, 2, figsize=(10,4))

axes[0].plot(x, x**2, x, exp(x))
axes[0].set_title("Normal scale")

axes[1].plot(x, x**2, x, exp(x))
axes[1].set_yscale("log")
axes[1].set_title("Logarithmic scale (y)");

fig

這裏寫圖片描述

自定義標號位置與符號

set_xticks 與 set_yticks 方法可以顯示地設置標號的位置, set_xticklabels 與 set_yticklabels 爲每一個標號設置符號:
這裏寫圖片描述

科學計數法

如果軸上涉及非常大的數,最好使用科學計數法:

fig, ax = plt.subplots(1, 1)

ax.plot(x, x**2, x, exp(x))
ax.set_title("scientific notation")

ax.set_yticks([0, 50, 100, 150])

from matplotlib import ticker
formatter = ticker.ScalarFormatter(useMathText=True)
formatter.set_scientific(True) 
formatter.set_powerlimits((-1,1)) 
ax.yaxis.set_major_formatter(formatter) 

fig

這裏寫圖片描述

軸上數與標籤的間距

# distance between x and y axis and the numbers on the axes
rcParams['xtick.major.pad'] = 5
rcParams['ytick.major.pad'] = 5

fig, ax = plt.subplots(1, 1)

ax.plot(x, x**2, x, exp(x))
ax.set_yticks([0, 50, 100, 150])

ax.set_title("label and axis spacing")

# padding between axis label and axis numbers
ax.xaxis.labelpad = 5
ax.yaxis.labelpad = 5

ax.set_xlabel("x")
ax.set_ylabel("y");

fig

這裏寫圖片描述

調整座標軸的位置:

fig, ax = plt.subplots(1, 1)

ax.plot(x, x**2, x, exp(x))
ax.set_yticks([0, 50, 100, 150])

ax.set_title("title")
ax.set_xlabel("x")
ax.set_ylabel("y")

fig.subplots_adjust(left=0.15, right=.9, bottom=0.1, top=0.9);

fig

座標軸網格

grid 方法可以打開關閉網格線,也可以自定義網格的樣式:

fig, axes = plt.subplots(1, 2, figsize=(10,3))

# default grid appearance
axes[0].plot(x, x**2, x, x**3, lw=2)
axes[0].grid(True)

# custom grid appearance
axes[1].plot(x, x**2, x, x**3, lw=2)
axes[1].grid(color='b', alpha=0.5, linestyle='dashed', linewidth=0.5)

fig

這裏寫圖片描述

改變軸的屬性:

fig, ax = plt.subplots(figsize=(6,2))

ax.spines['bottom'].set_color('blue')
ax.spines['top'].set_color('blue')

ax.spines['left'].set_color('red')
ax.spines['left'].set_linewidth(2)

# turn off axis spine to the right
ax.spines['right'].set_color("none")
ax.yaxis.tick_left() # only ticks on the left side

fig

這裏寫圖片描述

雙座標軸

twinx 與 twiny 函數能設置雙座標軸:

fig, ax1 = plt.subplots()

ax1.plot(x, x**2, lw=2, color="blue")
ax1.set_ylabel(r"area $(m^2)$", fontsize=18, color="blue")
for label in ax1.get_yticklabels():
    label.set_color("blue")

ax2 = ax1.twinx()
ax2.plot(x, x**3, lw=2, color="red")
ax2.set_ylabel(r"volume $(m^3)$", fontsize=18, color="red")
for label in ax2.get_yticklabels():
    label.set_color("red")

fig

這裏寫圖片描述

設置座標原點在(0,0)點

fig, ax = plt.subplots()

ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')

ax.xaxis.set_ticks_position('bottom')
ax.spines['bottom'].set_position(('data',0)) # set position of x spine to x=0

ax.yaxis.set_ticks_position('left')
ax.spines['left'].set_position(('data',0))   # set position of y spine to y=0

xx = np.linspace(-0.75, 1., 100)
ax.plot(xx, xx**3);

fig

這裏寫圖片描述

其他 2D 圖表風格

包括一般的 plot 方法, 還有很多其他函數能夠生成不同類型的圖表

from numpy import *

n = array([0,1,2,3,4,5])

fig, axes = plt.subplots(1, 4, figsize=(12,3))

axes[0].scatter(xx, xx + 0.25*random.randn(len(xx)))
axes[0].set_title("scatter")

axes[1].step(n, n**2, lw=2)
axes[1].set_title("step")

axes[2].bar(n, n**2, align="center", width=0.5, alpha=0.5)
axes[2].set_title("bar")

axes[3].fill_between(x, x**2, x**3, color="green", alpha=0.5);
axes[3].set_title("fill_between");

fig

這裏寫圖片描述

# polar plot using add_axes and polar projection
fig = plt.figure()
ax = fig.add_axes([0.0, 0.0, .6, .6], polar=True)
t = linspace(0, 2 * pi, 100)
ax.plot(t, t, color='blue', lw=3);
fig

這裏寫圖片描述

直方圖

# A histogram
n = np.random.randn(100000)
fig, axes = plt.subplots(1, 2, figsize=(12,4))

axes[0].hist(n)
axes[0].set_title("Default histogram")
axes[0].set_xlim((min(n), max(n)))

axes[1].hist(n, cumulative=True, bins=50)
axes[1].set_title("Cumulative detailed histogram")
axes[1].set_xlim((min(n), max(n)));

fig

這裏寫圖片描述

文本註釋

text 函數可以做文本註釋,且支持 LaTeX 格式:

fig, ax = plt.subplots()

ax.plot(xx, xx**2, xx, xx**3)

ax.text(0.15, 0.2, r"$y=x^2$", fontsize=20, color="blue")
ax.text(0.65, 0.1, r"$y=x^3$", fontsize=20, color="green");

fig

這裏寫圖片描述

帶有多子圖與插圖的圖

fig.add_axes 在圖中加入新座標軸subplots, subplot2grid,gridspec等 子圖佈局管理器
subplots:

fig, ax = plt.subplots(2, 3) #兩行三列

subplot2grid

fig = plt.figure()
ax1 = plt.subplot2grid((3,3), (0,0), colspan=3)
ax2 = plt.subplot2grid((3,3), (1,0), colspan=2)
ax3 = plt.subplot2grid((3,3), (1,2), rowspan=2)
ax4 = plt.subplot2grid((3,3), (2,0))
ax5 = plt.subplot2grid((3,3), (2,1))
fig.tight_layout()

fig

這裏寫圖片描述

gridspec

import matplotlib.gridspec as gridspec

fig = plt.figure()

gs = gridspec.GridSpec(2, 3, height_ratios=[2,1], width_ratios=[1,2,1])
for g in gs:
    ax = fig.add_subplot(g)

fig.tight_layout()

fig

這裏寫圖片描述

add_axes

fig, ax = plt.subplots()

ax.plot(xx, xx**2, xx, xx**3)
fig.tight_layout()

# inset
inset_ax = fig.add_axes([0.2, 0.55, 0.35, 0.35]) # X, Y, width, height

inset_ax.plot(xx, xx**2, xx, xx**3)
inset_ax.set_title('zoom near origin')

# set axis range
inset_ax.set_xlim(-.2, .2)
inset_ax.set_ylim(-.005, .01)

# set axis tick locations
inset_ax.set_yticks([0, 0.005, 0.01])
inset_ax.set_xticks([-0.1,0,.1]);

fig

這裏寫圖片描述

顏色映射圖與輪廓圖

顏色映射圖與輪廓圖適合繪製兩個變量的函數。有許多預定義的顏色映射圖

alpha = 0.7
phi_ext = 2 * pi * 0.5

def flux_qubit_potential(phi_m, phi_p):
    return 2 + alpha - 2 * cos(phi_p)*cos(phi_m) - alpha * cos(phi_ext - 2*phi_p)

phi_m = linspace(0, 2*pi, 100)
phi_p = linspace(0, 2*pi, 100)
X,Y = meshgrid(phi_p, phi_m)
Z = flux_qubit_potential(X, Y).T

pcolor

fig, ax = plt.subplots()

p = ax.pcolor(X/(2*pi), Y/(2*pi), Z, cmap=matplotlib.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max())
cb = fig.colorbar(p, ax=ax)

fig

這裏寫圖片描述

imshow

fig, ax = plt.subplots()

im = ax.imshow(Z, cmap=matplotlib.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 1, 0, 1])
im.set_interpolation('bilinear')

cb = fig.colorbar(im, ax=ax)

fig

contour

fig, ax = plt.subplots()

cnt = ax.contour(Z, cmap=matplotlib.cm.RdBu, vmin=abs(Z).min(), vmax=abs(Z).max(), extent=[0, 1, 0, 1])

fig

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章