文章目录

  • 写在篇前
  • 三维绘图函数
  • LinePlot
  • ScatterPlot
  • WireframePlot
  • SurfacePlot
  • ContourPlot
  • FilledContourPlot
  • PolygonPlot
  • BarPlot
  • Text
  • 写在篇后


写在篇前

  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()

python matplotlib 三维地图 matplotlib三维绘图_ide

ScatterPlot

  • Axes3D.``scatter(xs, ys, zs=0, zdir=‘z’, s=20, c=None, depthshade=True, *args, **kwargs)
    返回Patch3DCollection,
      其他参数向下传递给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()

python matplotlib 三维地图 matplotlib三维绘图_python_02

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()

python matplotlib 三维地图 matplotlib三维绘图_matplotlib_03

SurfacePlot

  • Axes3D.``plot_surface(X, Y, Z, *args, norm=None, vmin=None, vmax=None, lightsource=None, **kwargs)
      这个函数算是比较常用的函数,用于绘制三维表面图,让人惊艳的是它的着色效果。

Argument

Description

X, YZ

坐标点

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()

python matplotlib 三维地图 matplotlib三维绘图_二维_04

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()

python matplotlib 三维地图 matplotlib三维绘图_matplotlib_05

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()

python matplotlib 三维地图 matplotlib三维绘图_ide_06

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()

python matplotlib 三维地图 matplotlib三维绘图_ide_07

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()

python matplotlib 三维地图 matplotlib三维绘图_二维_08

写在篇后

  三维绘图不是很常用,主要就是scatterPlot以及surfacePlot稍微更常用。