matplotlib(六)三維作圖
寫在篇前
matplotlib也支援三維作圖,但是相對於matlab來講,感覺功能更弱。當然話說回來,三維作圖用的場景相對也更少,所以呢,有一定的知識儲備就夠了。matplotlib繪製三維圖形依賴於mpl_toolkits.mplot3d
,用法也比較簡單,只需要一個關鍵字引數projection='3d'
就可以建立三維Axes。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d' )
你可能會看到有的教程寫的是ax = Axes3D(fig)
,這是version1.0.0之前的寫法
三維繪圖函式
LinePlot
-
Axes3D.``plot
(xs, ys, *args, zdir=‘z’, **kwargs)其他引數向下傳遞給
plot
函式
Argument | Description |
---|---|
xs, ys | x、y 座標 |
zs | z 座標,可以是一個標量或一個x*y維矩陣 |
zdir | 當繪製二維影象時的z軸方向 |
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib. pyplot as plt
plt.rcParams['legend.fontsize'] = 10
fig = plt.figure()
ax = fig.gca(projection='3d') # get current axes
# Prepare arrays x, y, z
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
z = np.linspace(-2, 2, 100)
r = z**2 + 1
x = r * np.sin(theta)
y = r * np.cos(theta)
ax.plot(x, y, z, label= 'parametric curve')
ax.legend() # legend content dertermined by label above
plt.show()
ScatterPlot
-
Axes3D.``scatter
(xs, ys, zs=0, zdir=‘z’, s=20, c=None, depthshade=True, *args, **kwargs)其他引數向下傳遞給
plot
函式Argument Description xs, ys x,y座標點 zs z 座標,可以是一個標量或一個x*y維矩陣,預設是0. zdir 當繪製二維影象時的z軸方向 s size,即散點大小 c 顏色對映,其取值可以是非常多型別,有時間專門寫一篇講解 depthshade 是否渲染景深(或則就說陰影吧),預設是True.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# Fixing random state for reproducibility
np.random.seed(19680801)
def randrange(n, vmin, vmax):
'''
Helper function to make an array of random numbers having shape (n, )
with each number distributed Uniform(vmin, vmax).
'''
return (vmax - vmin)*np.random.rand(n) + vmin
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
n = 100
# For each set of style and range settings, plot n random points in the box
# defined by x in [23, 32], y in [0, 100], z in [zlow, zhigh].
for c, m, zlow, zhigh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
xs = randrange(n, 23, 32)
ys = randrange(n, 0, 100)
zs = randrange(n, zlow, zhigh)
ax.scatter(xs, ys, zs, c=c, marker=m)
ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')
plt.show()
WireframePlot
-
Axes3D.``plot_wireframe
(X, Y, Z, *args, **kwargs)Argument Description X, Y,Z 座標點 rcount,ccount 取樣數,越大采樣越多,預設50 rstride,cstride 取樣步長,越小取樣越多 **kwargs 其他引數向下傳入Line3DCollection from mpl_toolkits.mplot3d import axes3d import matplotlib.pyplot as plt fig = plt.figure() ax = fig.add_subplot(111, projection='3d') # Grab some test data. X, Y, Z = axes3d.get_test_data(0.05) # Plot a basic wireframe. ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10) plt.show()
SurfacePlot
-
Axes3D.``plot_surface
(X, Y, Z, *args, norm=None, vmin=None, vmax=None, lightsource=None, **kwargs)這個函式算是比較常用的函式,用於繪製三維表面圖,讓人驚豔的是它的著色效果。
Argument Description X, Y,Z 座標點 rcount,ccount,rstride,cstride 同上 color 定義surface patch的顏色,type:color-like cmap 定義surface patch的顏色,只不過是colorMap,type:colormap facecolors 指定單個patch的顏色, type:array-like of colors norm colormap的normalization, type:Normalize shade 陰影效果,type:boolean vmin, vmax normalization的邊界 **kwargs 向下傳遞到 Poly3DCollection
antialiased 抗鋸齒,type:boolean
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
# Make data.
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
# Plot the surface.
surf = ax.plot_surface(X, Y, Z, cmap=cm.coolwarm,
linewidth=0, antialiased=False)
# Customize the z axis.
ax.set_zlim(-1.01, 1.01)
ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))
# Add a color bar which maps values to colors.
fig.colorbar(surf, shrink=0.5, aspect=5)
plt.show()
ContourPlot
-
Axes3D.``contour
(X, Y, Z, *args, extend3d=False, stride=5, zdir=‘z’, offset=None, **kwargs)Argument Description X, Y,Z Data values as numpy.arrays extend3d 是否延申到3d空間 (default: False) *stride (extend3d的)取樣步長 zdir 同上 offset 繪製輪廓線在zdir垂直的水平面上的投影 其他位置、關鍵字引數向下傳遞到二維
contour()
函式
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
fig = plt.figure()
ax = fig.gca(projection='3d')
X, Y, Z = axes3d.get_test_data(0.05)
# Plot contour curves
cset = ax.contour(X, Y, Z, cmap=cm.coolwarm)
ax.clabel(cset, fontsize=9, inline=1) # function to label a contour
plt.show()
FilledContourPlot
Axes3D.``contourf
(X, Y, Z, *args, zdir=‘z’, offset=None, **kwargs)
Argument | Description |
---|---|
X, Y,Z | Data values as numpy.arrays |
zdir | 同上 |
offset | 繪製輪廓線在zdir垂直的水平面上的投影 |
其他位置、關鍵字引數向下傳遞到二維contourf()
,例子請參考上面的contour
PolygonPlot
-
Axes3D.``add_collection3d
(col, zs=0, zdir=‘z’)這個函式挺有趣,但是我沒有遇到過這種場景。它可以將三維 collection物件或二維collection物件加入到一個圖形中,包括:
-
PolyCollection
-
LineCollection
-
PatchCollection
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import from matplotlib.collections import PolyCollection import matplotlib.pyplot as plt from matplotlib import colors as mcolors import numpy as np # Fixing random state for reproducibility np.random.seed(19680801) def cc(arg): ''' Shorthand to convert 'named' colors to rgba format at 60% opacity. ''' return mcolors.to_rgba(arg, alpha=0.6) def polygon_under_graph(xlist, ylist): ''' Construct the vertex list which defines the polygon filling the space under the (xlist, ylist) line graph. Assumes the xs are in ascending order. ''' return [(xlist[0], 0.), *zip(xlist, ylist), (xlist[-1], 0.)] fig = plt.figure() ax = fig.gca(projection='3d') # Make verts a list, verts[i] will be a list of (x,y) pairs defining polygon i verts = [] # Set up the x sequence xs = np.linspace(0., 10., 26) # The ith polygon will appear on the plane y = zs[i] zs = range(4) for i in zs: ys = np.random.rand(len(xs)) verts.append(polygon_under_graph(xs, ys)) poly = PolyCollection(verts, facecolors=[cc('r'), cc('g'), cc('b'), cc('y')]) ax.add_collection3d(poly, zs=zs, zdir='y') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.set_xlim(0, 10) ax.set_ylim(-1, 4) ax.set_zlim(0, 1) plt.show()
-
BarPlot
-
Axes3D.``bar
(left, height, zs=0, zdir=‘z’, *args, **kwargs)其他引數向下傳遞給
bar
函式,返回Patch3DCollection
物件Argument Description left 條形圖水平座標 height 條形的高度 zs Z方向 zdir 同上 from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import import matplotlib.pyplot as plt import numpy as np # Fixing random state for reproducibility np.random.seed(19680801) fig = plt.figure() ax = fig.add_subplot(111, projection='3d') colors = ['r', 'g', 'b', 'y'] yticks = [3, 2, 1, 0] for c, k in zip(colors, yticks): # Generate the random data for the y=k 'layer'. xs = np.arange(20) ys = np.random.rand(20) # You can provide either a single color or an array with the same length as # xs and ys. To demonstrate this, we color the first bar of each set cyan. cs = [c] * len(xs) # Plot the bar graph given by xs and ys on the plane y=k with 80% opacity. ax.bar(xs, ys, zs=k, zdir='y', color=cs, alpha=0.8) ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') # On the y axis let's only label the discrete values that we have data for. ax.set_yticks(yticks) plt.show()
Text
-
Axes3D.``text
(x, y, z, s, zdir=None, **kwargs)text的內容其實也很繁雜,需要用一篇內容去探討,在三維中很重要的一點是要學會二維、三維文字的新增。
from mpl_toolkits.mplot3d import Axes3D # noqa: F401 unused import import matplotlib.pyplot as plt fig = plt.figure() ax = fig.gca(projection='3d') # Demo 1: zdir zdirs = (None, 'x', 'y', 'z', (1, 1, 0), (1, 1, 1)) xs = (1, 4, 4, 9, 4, 1) ys = (2, 5, 8, 10, 1, 2) zs = (10, 3, 8, 9, 1, 8) for zdir, x, y, z in zip(zdirs, xs, ys, zs): label = '(%d, %d, %d), dir=%s' % (x, y, z, zdir) ax.text(x, y, z, label, zdir) # Demo 2: color ax.text(9, 0, 0, "red", color='red') # Demo 3: text2D # Placement 0, 0 would be the bottom left, 1, 1 would be the top right. ax.text2D(0.05, 0.95, "2D Text", transform=ax.transAxes) # Tweaking display region and labels ax.set_xlim(0, 10) ax.set_ylim(0, 10) ax.set_zlim(0, 10) ax.set_xlabel('X axis') ax.set_ylabel('Y axis') ax.set_zlabel('Z axis') plt.show()
寫在篇後
三維繪圖不是很常用,主要就是scatterPlot以及surfacePlot稍微更常用。關於三維繪圖總結的也有點糙,更多關於matplotlib,可以閱讀參考我寫的同類文章請參考: