# Python 数据分析三剑客之 Matplotlib（十）：3D 图的绘制

TRHX

2020-06-08

Python 数据分析 / Matplotlib

字数统计:

6,079字

阅读时长≈

29分

Matplotlib 系列文章：

- Python 数据分析三剑客之 Matplotlib（一）：初识 Matplotlib 与其 matplotibrc 配置文件
- Python 数据分析三剑客之 Matplotlib（二）：文本描述 / 中文支持 / 画布 / 网格等基本图像属性
- Python 数据分析三剑客之 Matplotlib（三）：图例 / LaTeX / 刻度 / 子图 / 补丁等基本图像属性
- Python 数据分析三剑客之 Matplotlib（四）：线性图的绘制
- Python 数据分析三剑客之 Matplotlib（五）：散点图的绘制
- Python 数据分析三剑客之 Matplotlib（六）：直方图 / 柱状图 / 条形图的绘制
- Python 数据分析三剑客之 Matplotlib（七）：饼状图的绘制
- Python 数据分析三剑客之 Matplotlib（八）：等高线 / 等值线图的绘制
- Python 数据分析三剑客之 Matplotlib（九）：极区图 / 极坐标图 / 雷达图的绘制
- Python 数据分析三剑客之 Matplotlib（十）：3D 图的绘制
- Python 数据分析三剑客之 Matplotlib（十一）：最热门最常用的 50 个图表【译文】

专栏：

【NumPy 专栏】【Pandas 专栏】【Matplotlib 专栏】

推荐学习资料与网站：

【NumPy 中文网】【Pandas 中文网】【Matplotlib 中文网】【NumPy、Matplotlib、Pandas 速查表】

    1
    2
    3
    4
    5

    这里是一段防爬虫文本，请读者忽略。
    本文原创首发于 CSDN，作者 TRHX。
    博客首页：https://itrhx.blog.csdn.net/
    本文链接：https://itrhx.blog.csdn.net/article/details/106558131
    未经授权，禁止转载！恶意转载，后果自负！尊重原创，远离剽窃！

## 【01x00】了解 mplot3d Toolkit

mplot3d Toolkit 即 mplot3d 工具包，在 matplotlib 中使用 mplot3d 工具包可以绘制 3D 图。

mplot3d 官方文档：https://matplotlib.org/tutorials/toolkits/mplot3d.html

在 matplotlib 中，figure 为画布，axes 为绘图区，`fig.add_subplot()`、`plt.subplot()` 方法均可以创建子图，在绘制 3D 图时，某些 2D 图的参数也适用于 3D 图，在本文的示例中，可能会用到的一些没有具体解释的函数或者参数，其用法均可在前面的系列文章中找到：

- 《Python 数据分析三剑客之 Matplotlib（一）：初识 Matplotlib 与其 matplotibrc 配置文件》

- 《Python 数据分析三剑客之 Matplotlib（二）：文本描述 / 中文支持 / 画布 / 网格等基本图像属性》

- 《Python 数据分析三剑客之 Matplotlib（三）：图例 / LaTeX / 刻度 / 子图 / 补丁等基本图像属性》

绘制 3D 图的步骤：创建 Axes3D 对象，然后调用 Axes3D 的不同方法来绘制不同类型的 3D 图。以下介绍三种 Axes3D 对象创建的方法。

### 【01x01】Axes3D 对象创建方法一：Axes3D(fig)

在 Matplotlib 1.0.0 版本中，绘制 3D 图需要先导入 Axes3D 包，获取 figure 画布对象 fig 后，通过 Axes3D(fig) 方法来创建 Axes3D 对象，具体方法如下：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D

    # 获取 figure 画布并创建 Axes3D 对象
    fig = plt.figure()
    ax = Axes3D(fig)

    # 数据坐标
    z = np.linspace(0, 15, 1000)
    x = np.sin(z)
    y = np.cos(z)

    # 绘制线性图
    ax.plot(x, y, z)
    plt.show()

### 【01x02】Axes3D 对象创建方法二：add_subplot

在 Matplotlib 3.2.0 版本中，绘制 3D 图可以通过创建子图，然后指定 projection 参数 为 3d 即可，返回的 ax 为 Axes3D 对象，以下两种方法均可：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    import numpy as np
    import matplotlib.pyplot as plt

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    # 数据坐标
    z = np.linspace(0, 15, 1000)
    x = np.sin(z)
    y = np.cos(z)

    # 绘制线性图
    ax.plot(x, y, z)
    plt.show()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

    import numpy as np
    import matplotlib.pyplot as plt

    # 通过子图创建 Axes3D 对象
    ax = plt.subplot(111, projection='3d')

    # 数据坐标
    z = np.linspace(0, 15, 1000)
    x = np.sin(z)
    y = np.cos(z)

    # 绘制线性图
    ax.plot(x, y, z)
    plt.show()

### 【01x03】Axes3D 对象创建方法三：gca

除了以上两种方法以外，还可以先获取画布对象 fig，再通过 `fig.gca()` 方法获取当前绘图区（gca = Get Current Axes），然后指定 projection 参数 为 3d 即可，返回的 ax 为 Axes3D 对象。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15

    import numpy as np
    import matplotlib.pyplot as plt

    # 依次获取画布和绘图区并创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.gca(projection='3d')

    # 数据坐标
    z = np.linspace(0, 15, 1000)
    x = np.sin(z)
    y = np.cos(z)

    # 绘制线性图
    ax.plot(x, y, z)
    plt.show()

以上三种方法运行结果均为下图：

<fancybox>
</fancybox>

## 【02x00】cmap 与 colorbar

默认情况下，散点图、线性图、曲面图等将以纯色着色，但可以通过提供 cmap 参数支持颜色映射。cmap 参数用于设置一些特殊的颜色组合，如渐变色等，参数取值通常为 Colormap 中的值，具体取值可参见下图：

官方文档：https://matplotlib.org/tutorials/colors/colormaps.html

<fancybox>
</fancybox>

如果使用了 cmap 参数，则可以使用 `pyplot.colorbar()` 函数来绘制一个色条，即颜色对照条。

基本语法：`matplotlib.pyplot.colorbar([mappable=None, cax=None, ax=None, **kw])`

部分参数解释如下表，其他参数，如长度，宽度等请参考官方文档。

参数 | 描述
--- | ---
mappable | 要设置色条的图像对象，该参数对于 `Figure.colorbar` 方法是必需的，但对于 `pyplot.colorbar` 函数是可选的
cax | 可选项，要绘制色条的轴
ax | 可选项，设置色条的显示位置，通常在一个画布上有多个子图时使用
**kw | 可选项，其他关键字参数，参考官方文档

## 【03x00】3D 线性图：Axes3D.plot

基本方法：`Axes3D.plot(xs, ys[, zs, zdir='z', *args, **kwargs])`

参数 | 描述
--- | ---
xs | 一维数组，点的 x 轴坐标
ys | 一维数组，点的 y 轴坐标
zs | 一维数组，可选项，点的 z 轴坐标
zdir | 可选项，在 3D 轴上绘制 2D 数据时，数据必须以 xs，ys 的形式传递， 若此时将 zdir 设置为 ‘y’，数据将会被绘制到 x-z 轴平面上，默认为 ‘z’
**kwargs | 其他关键字参数，可选项，可参见 matplotlib.axes.Axes.plot

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34

    import numpy as np
    import matplotlib.pyplot as plt

    # 设置中文显示
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 依次获取画布和绘图区并创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.gca(projection='3d')

    # 第一条3D线性图数据
    theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
    z1 = np.linspace(-2, 2, 100)
    r = z1**2 + 1
    x1 = r * np.sin(theta)
    y1 = r * np.cos(theta)

    # 第二条3D线性图数据
    z2 = np.linspace(-3, 3, 100)
    x2 = np.sin(z2)
    y2 = np.cos(z2)

    # 绘制3D线性图
    ax.plot(x1, y1, z1, color='b', label='3D 线性图一')
    ax.plot(x2, y2, z2, color='r', label='3D 线性图二')

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel、plt.legend...
    ax.set_title('绘制 3D 线性图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴', color='r', fontsize='12')
    ax.set_ylabel('y 轴', color='g', fontsize='12')
    ax.set_zlabel('z 轴', color='b', fontsize='12')
    ax.legend()

    plt.show()

<fancybox>
</fancybox>

## 【04x00】3D 散点图：Axes3D.scatter

基本方法：`Axes3D.scatter(xs, ys[, zs=0, zdir='z', s=20, c=None, depthshade=True, *args, **kwargs])`

参数 | 描述
--- | ---
xs | 一维数组，点的 x 轴坐标
ys | 一维数组，点的 y 轴坐标
zs | 一维数组，可选项，点的 z 轴坐标
zdir | 可选项，在 3D 轴上绘制 2D 数据时，数据必须以 xs，ys 的形式传递， 若此时将 zdir 设置为 ‘y’，数据将会被绘制到 x-z 轴平面上，默认为 ‘z’
s | 标量或数组类型，可选项，标记的大小，默认 20
c | 标记的颜色，可选项，可以是单个颜色或者一个颜色列表 支持英文颜色名称及其简写、十六进制颜色码等，更多颜色示例参见官网 Color Demo
depthshade | bool 值，可选项，默认 True，是否为散点标记着色以提供深度外观
**kwargs | 其他关键字参数，可选项，可参见 scatter

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import numpy as np
    import matplotlib.pyplot as plt

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 依次获取画布和绘图区并创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    n = 100

    def randrange(n, vmin, vmax):
        return (vmax - vmin)*np.random.rand(n) + vmin

    '''
    定义绘制 n 个随机点，设置每一组数据点的样式和范围
    x轴数据位于[23，32]区间，y轴数据位于[0，100]区间，z轴数据位于[zlow，zhigh]区间
    '''
    for m, zlow, zhigh in [('o', -50, -25), ('^', -30, -5)]:
        xs = randrange(n, 23, 32)
        ys = randrange(n, 0, 100)
        zs = randrange(n, zlow, zhigh)
        ax.scatter(xs, ys, zs, marker=m)

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel...
    ax.set_title('绘制 3D 散点图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴', color='b')
    ax.set_ylabel('y 轴', color='b')
    ax.set_zlabel('z 轴', color='b')

    plt.show()

<fancybox>
</fancybox>

## 【05x00】3D 线框图：Axes3D.plot_wireframe

基本方法：`Axes3D.plot_wireframe(X, Y, Z[, *args, **kwargs])`

参数 | 描述
--- | ---
X | 二维数组，x 轴数据
Y | 二维数组，y 轴数据
Z | 二维数组，z 轴数据
**kwargs | 其他关键字参数，可选项，如线条样式颜色等，可参见 Line3DCollection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import numpy as np
    import matplotlib.pyplot as plt

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    # 定义Z轴坐标的生成方法
    def f(m, n):
        return np.sin(np.sqrt(m ** 2 + n ** 2))

    # 设置3D线框图数据
    x = np.linspace(-6, 6, 30)
    y = np.linspace(-6, 6, 30)
    # 生成网格点坐标矩阵，该方法在系列文章八中有具体介绍
    X, Y = np.meshgrid(x, y)
    Z = f(X, Y)

    # 绘制3D线框图
    ax.plot_wireframe(X, Y, Z, color='c')

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel...
    ax.set_title('绘制 3D 线框图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')

    plt.show()

<fancybox>
</fancybox>

## 【06x00】3D 曲面图：Axes3D.plot_surface

基本方法：`Axes3D.plot_surface(X, Y, Z[, *args, vmin=None, vmax=None, **kwargs])`

参数 | 描述
--- | ---
X | 二维数组，x 轴数据
Y | 二维数组，y 轴数据
Z | 二维数组，z 轴数据
vmin / vmax | 规定数据界限
**kwargs | 其他关键字参数，可选项，如线条样式颜色等，可参见 Line3DCollection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import numpy as np
    import matplotlib.pyplot as plt

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    # 设置3D曲面图数据
    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)

    # 绘制3D曲面图并添加色条（长度0.8）
    surface = ax.plot_surface(X, Y, Z, cmap='rainbow', antialiased=False)
    fig.colorbar(surface, shrink=0.8)

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel...
    ax.set_title('绘制 3D 曲面图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')
    # 调整观察角度和方位角，俯仰角25度，方位角40度
    ax.view_init(25, 40)
    # 设置Z轴刻度界限
    ax.set_zlim(-2, 2)

    plt.show()

<fancybox>
</fancybox>

    1
    2
    3
    4
    5

    这里是一段防爬虫文本，请读者忽略。
    本文原创首发于 CSDN，作者 TRHX。
    博客首页：https://itrhx.blog.csdn.net/
    本文链接：https://itrhx.blog.csdn.net/article/details/106558131
    未经授权，禁止转载！恶意转载，后果自负！尊重原创，远离剽窃！

## 【07x00】3D 柱状图：Axes3D.bar

基本方法：`Axes3D.bar(left, height, zs=0, zdir='z', *args, **kwargs)`

参数 | 描述
--- | ---
left | 一维数组，柱状图最左侧位置的 x 坐标
height | 一维数组，柱状图的高度（y 坐标）
zs | 第 i 个多边形将出现在平面 y=zs[i] 上
zdir | 可选项，在 3D 轴上绘制 2D 数据时，数据必须以 xs，ys 的形式传递， 若此时将 zdir 设置为 ‘y’，数据将会被绘制到 x-z 轴平面上，默认为 ‘z’
**kwargs | 其他关键字参数，参见 matplotlib.axes.Axes.bar

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    import matplotlib.pyplot as plt
    import numpy as np

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    colors = ['r', 'g', 'b', 'y']
    yticks = [3, 2, 1, 0]

    # 设置3D柱状图数据并绘制图像
    for c, k in zip(colors, yticks):
        xs = np.arange(20)
        ys = np.random.rand(20)
        cs = [c] * len(xs)
        ax.bar(xs, ys, zs=k, zdir='y', color=cs, alpha=0.8)

    # 设置图像标题、坐标标签以及范围
    ax.set_title('绘制 3D 柱状图示例', pad=15, fontsize='12')
    ax.set_xlabel('X 轴')
    ax.set_ylabel('Y 轴')
    ax.set_zlabel('Z 轴')
    ax.set_yticks(yticks)

    plt.show()

<fancybox>
</fancybox>

## 【08x00】3D 箭头图：Axes3D.quiver

基本方法：`Axes3D.quiver(X, Y, Z, U, V, W, length=1, arrow_length_ratio=0.3, pivot='tail', normalize=False, **kwargs)`

参数 | 描述
--- | ---
X, Y, Z | 数组形式，箭头位置的 x、y 和 z 轴坐标（默认为箭头尾部）
U, V, W | 数组形式，箭头向量的 x、y 和 z 轴分量
length | float 类型，每个箭筒的长度，默认为 1.0
arrow_length_ratio | float 类型，箭头相对于箭身的比率，默认为 0.3
pivot | 箭头在网格点上的位置；箭头围绕该点旋转，因此命名为 pivot，默认为 ‘tail’ 可选项：`'tail'`：尾部；`'middle'`：中间；`'tip'`：尖端
normalize | bool 类型，如果为 True，则所有箭头的长度都将相同 默认为 False，即箭头的长度取决于 U、V、W 的值
**kwargs | 其他关键字参数，参见 LineCollection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import matplotlib.pyplot as plt
    import numpy as np

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 依次获取画布和绘图区并创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.gca(projection='3d')

    # 设置箭头位置
    x, y, z = np.meshgrid(np.arange(-0.8, 1, 0.2),
                          np.arange(-0.8, 1, 0.2),
                          np.arange(-0.8, 1, 0.8))

    # 设置箭头数据
    u = np.sin(np.pi * x) * np.cos(np.pi * y) * np.cos(np.pi * z)
    v = -np.cos(np.pi * x) * np.sin(np.pi * y) * np.cos(np.pi * z)
    w = (np.sqrt(2.0 / 3.0) * np.cos(np.pi * x) * np.cos(np.pi * y) * np.sin(np.pi * z))

    # 绘制 3D 箭头图
    ax.quiver(x, y, z, u, v, w, length=0.1, normalize=True)

    # 设置图像标题、坐标标签
    ax.set_title('绘制 3D 箭头图示例', pad=15, fontsize='12')
    ax.set_xlabel('X 轴')
    ax.set_ylabel('Y 轴')
    ax.set_zlabel('Z 轴')

    # 调整观察角度，俯仰角20度
    ax.view_init(20)

    plt.show()

<fancybox>
</fancybox>

## 【09x00】3D 等高线图：Axes3D.contour

基本方法：`Axes3D.contour(X, Y, Z[, *args, extend3d=False, stride=5, zdir='z', offset=None, **kwargs])`

参数 | 描述
--- | ---
X | 一维数组，x 轴数据
Y | 一维数组，y 轴数据
Z | 一维数组，z 轴数据
extend3d | bool 值，可选项，是否以 3D 延伸轮廓，默认 False
stride | int 类型，可选项，用于延伸轮廓的步长
zdir | 可选项，在 3D 轴上绘制 2D 数据时，数据必须以 xs，ys 的形式传递， 若此时将 zdir 设置为 ‘y’，数据将会被绘制到 x-z 轴平面上，默认为 ‘z’
offset | 标量，可选项，如果指定，则在垂直于 zdir 的平面上的位置绘制轮廓线的投影
**kwargs | 其他关键字参数，可选项，可参见 matplotlib.axes.Axes.contour

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import numpy as np
    import matplotlib.pyplot as plt

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure(figsize=(8, 4.8))
    ax = fig.add_subplot(111, projection='3d')

    # 设置等高线数据
    X = np.arange(-2.0, 2.0, 0.01)
    Y = np.arange(-2.0, 2.0, 0.01)
    # 生成网格点坐标矩阵
    m, n = np.meshgrid(X, Y)

    # 指定一个函数用于计算每个点的高度，也可以直接使用二维数组储存每个点的高度
    def f(a, b):
        return (1 - b ** 5 + a ** 5) * np.exp(-a ** 2 - b ** 2)

    # 绘制3D等高线图并添加色条图（长度0.8）
    contour = ax.contour(X, Y, f(m, n), cmap='rainbow')
    fig.colorbar(contour, shrink=0.8)

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel...
    ax.set_title('绘制 3D 等高线图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')

    plt.show()

<fancybox>
</fancybox>

## 【10x00】3D 等高线填充图：Axes3D.contourf

基本语法：`Axes3D.contourf(X, Y, Z[, *args, zdir='z', offset=None, **kwargs])`

参数 | 描述
--- | ---
X | 一维数组，x 轴数据
Y | 一维数组，y 轴数据
Z | 一维数组，z 轴数据
zdir | 可选项，在 3D 轴上绘制 2D 数据时，数据必须以 xs，ys 的形式传递， 若此时将 zdir 设置为 ‘y’，数据将会被绘制到 x-z 轴平面上，默认为 ‘z’
offset | 标量，可选项，如果指定，则在垂直于 zdir 的平面上的位置绘制轮廓线的投影
**kwargs | 其他关键字参数，可选项，可参见 matplotlib.axes.Axes.contourf

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import numpy as np
    import matplotlib.pyplot as plt

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure(figsize=(8, 4.8))
    ax = fig.add_subplot(111, projection='3d')

    # 设置等高线数据
    X = np.arange(-2.0, 2.0, 0.01)
    Y = np.arange(-2.0, 2.0, 0.01)
    # 生成网格点坐标矩阵
    m, n = np.meshgrid(X, Y)

    # 指定一个函数用于计算每个点的高度，也可以直接使用二维数组储存每个点的高度
    def f(a, b):
        return (1 - b ** 5 + a ** 5) * np.exp(-a ** 2 - b ** 2)

    # 绘制3D等高线图并添加色条图（长度0.8）
    contourf = ax.contourf(X, Y, f(m, n), cmap='rainbow')
    fig.colorbar(contourf, shrink=0.8)

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel...
    ax.set_title('绘制 3D 等高线填充图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')

    plt.show()

<fancybox>
</fancybox>

## 【11x00】3D 三角曲面图：Axes3D.plot_trisurf

基本方法：`Axes3D.plot_trisurf(X, Y, Z[, *args, color=None, vmin=None, vmax=None, **kwargs])`

参数 | 描述
--- | ---
X | 一维数组，x 轴数据
Y | 一维数组，y 轴数据
Z | 一维数组，z 轴数据
color | 曲面表面的颜色
vmin / vmax | 规定数据界限
**kwargs | 可选项，其他关键字参数，可参见 Poly3DCollection

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29

    import matplotlib.pyplot as plt
    import numpy as np

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 获取 figure 画布并通过子图创建 Axes3D 对象
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')

    n_radii = 8
    n_angles = 36

    radii = np.linspace(0.125, 1.0, n_radii)
    angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)[..., np.newaxis]
    x = np.append(0, (radii*np.cos(angles)).flatten())
    y = np.append(0, (radii*np.sin(angles)).flatten())
    z = np.sin(-x*y)

    # 绘制3D三角曲面图并添加色条（长度0.8）
    trisurf = ax.plot_trisurf(x, y, z, cmap='rainbow')
    fig.colorbar(trisurf, shrink=0.8)

    # 设置标题、轴标签、图例，也可以直接使用 plt.title、plt.xlabel...
    ax.set_title('绘制 3D 三角曲面图示例', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')

    plt.show()

<fancybox>
</fancybox>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.tri as mtri

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    fig = plt.figure(figsize=(15, 6))

    # ============ 第一个示例图 ============ #

    ax = fig.add_subplot(1, 2, 1, projection='3d')

    u = np.linspace(0, 2.0 * np.pi, endpoint=True, num=50)
    v = np.linspace(-0.5, 0.5, endpoint=True, num=10)
    u, v = np.meshgrid(u, v)
    u, v = u.flatten(), v.flatten()

    x = (1 + 0.5 * v * np.cos(u / 2.0)) * np.cos(u)
    y = (1 + 0.5 * v * np.cos(u / 2.0)) * np.sin(u)
    z = 0.5 * v * np.sin(u / 2.0)

    tri = mtri.Triangulation(u, v)

    trisurf_1 = ax.plot_trisurf(x, y, z, triangles=tri.triangles, cmap='cool')
    fig.colorbar(trisurf_1, shrink=0.8)
    ax.set_zlim(-1, 1)

    ax.set_title('绘制 3D 三角曲面图示例一', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')

    # ============ 第二个示例图 ============ #

    ax = fig.add_subplot(1, 2, 2, projection='3d')

    n_angles = 36
    n_radii = 8
    min_radius = 0.25
    radii = np.linspace(min_radius, 0.95, n_radii)

    angles = np.linspace(0, 2*np.pi, n_angles, endpoint=False)
    angles = np.repeat(angles[..., np.newaxis], n_radii, axis=1)
    angles[:, 1::2] += np.pi/n_angles

    x = (radii*np.cos(angles)).flatten()
    y = (radii*np.sin(angles)).flatten()
    z = (np.cos(radii)*np.cos(3*angles)).flatten()

    triang = mtri.Triangulation(x, y)

    xmid = x[triang.triangles].mean(axis=1)
    ymid = y[triang.triangles].mean(axis=1)
    mask = xmid**2 + ymid**2 < min_radius**2
    triang.set_mask(mask)

    trisurf_2 = ax.plot_trisurf(triang, z, cmap='hsv')
    fig.colorbar(trisurf_2, shrink=0.8)

    ax.set_title('绘制 3D 三角曲面图示例二', pad=15, fontsize='12')
    ax.set_xlabel('x 轴')
    ax.set_ylabel('y 轴')
    ax.set_zlabel('z 轴')

    plt.show()

<fancybox>
</fancybox>

## 【12x00】将 2D 图像聚合到 3D 图像中：Axes3D.add_collection3d

基本方法：`Axes3D.add_collection3d(col, zs=0, zdir='z')`

参数 | 描述
--- | ---
col | PolyCollection / LineCollection / PatchCollection 对象
zs | 第 i 个多边形将出现在平面 y=zs[i] 上
zdir | 可选项，在 3D 轴上绘制 2D 数据时，数据必须以 xs，ys 的形式传递， 若此时将 zdir 设置为 ‘y’，数据将会被绘制到 x-z 轴平面上，默认为 ‘z’

该函数一般用来向图形中添加 3D 集合对象，以下用一个示例来展示某个地区在不同年份和不同月份的降水量：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.collections import PolyCollection

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    fig = plt.figure()
    ax = fig.gca(projection='3d')

    np.random.seed(59)
    month = np.arange(0, 13)
    years = [2017, 2018, 2019, 2020]

    precipitation = []
    for year in years:
        value = np.random.rand(len(month)) * 300
        value[0], value[-1] = 0, 0
        precipitation.append(list(zip(month, value)))

    poly = PolyCollection(precipitation, facecolors=['r', 'g', 'b', 'y'], alpha=.6)
    ax.add_collection3d(poly, zs=years, zdir='y')

    ax.set_title('2D 图像聚合到 3D 图像示例', pad=15, fontsize='12')
    ax.set_xlabel('月份')
    ax.set_ylabel('年份')
    ax.set_zlabel('降水量')
    ax.set_xlim3d(0, 12)
    ax.set_ylim3d(2016, 2021)
    ax.set_zlim3d(0, 300)

    plt.show()

<fancybox>
</fancybox>

此外，该方法也常被用于绘制 3D 多边形图，即多边体，示例如下：

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32

    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    fig = plt.figure()
    ax = fig.gca(projection='3d')

    # 六面体顶点和面
    verts = [(0, 0, 0), (0, 1, 0), (1, 1, 0), (1, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1), (1, 0, 1)]
    faces = [[0, 1, 2, 3], [4, 5, 6, 7], [0, 1, 5, 4], [1, 2, 6, 5], [2, 3, 7, 6], [0, 3, 7, 4]]

    # 获取每个面的顶点
    poly3d = [[verts[vert_id] for vert_id in face] for face in faces]

    # 绘制顶点
    x, y, z = zip(*verts)
    ax.scatter(x, y, z)
    # 绘制多边形面
    ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.5))
    # 绘制多边形的边
    ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.5, linestyles=':'))

    # 设置图像标题、坐标标签以及范围
    ax.set_title('绘制多边体示例', pad=15, fontsize='12')
    ax.set_xlabel('X 轴')
    ax.set_ylabel('Y 轴')
    ax.set_zlabel('Z 轴')
    ax.set_xlim3d(-0.5, 1.5)
    ax.set_ylim3d(-0.5, 1.5)
    ax.set_zlim3d(-0.5, 1.5)
    plt.show()

<fancybox>
</fancybox>

## 【13x00】3D 图添加文本描述：Axes3D.text

基本方法：`Axes3D.text(x, y, z, s[, zdir=None, **kwargs])`

参数 | 描述
--- | ---
x, y, z | 文本位置的 x、y、z 轴坐标
s | 要添加的文本
zdir | 可选项，若将 zdir 设置为 ‘y’，文本将会被投影到 x-z 轴平面上，默认为 None
**kwargs | 其他关键字参数，参见 matplotlib.text

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

    import matplotlib.pyplot as plt

    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']

    # 依次获取画布和绘图区并创建 Axes3D 对象
    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：设置颜色
    ax.text(9, 0, 0, "red", color='red')

    # Demo 3: text2D，位置(0，0)为左下角，(1，1)为右上角。
    ax.text2D(0.05, 0.95, "2D Text", transform=ax.transAxes)

    # 设置坐标轴界限和标签
    ax.set_xlim(0, 10)
    ax.set_ylim(0, 10)
    ax.set_zlim(0, 10)
    ax.set_xlabel('X 轴')
    ax.set_ylabel('Y 轴')
    ax.set_zlabel('Z 轴')

    plt.show()

<fancybox>
</fancybox>

    1
    2
    3
    4
    5

    这里是一段防爬虫文本，请读者忽略。
    本文原创首发于 CSDN，作者 TRHX。
    博客首页：https://itrhx.blog.csdn.net/
    本文链接：https://itrhx.blog.csdn.net/article/details/106558131
    未经授权，禁止转载！恶意转载，后果自负！尊重原创，远离剽窃！

您的喜欢是作者写作最大的动力！❤️

- PayPal
- AliPay
- WeChatPay
- QQPay

Donate

最后更新于 2020年8月6日

Matplotlib

3D图

###### 上一页

#### Python 数据分析三剑客之 Matplotlib（十一）：最常用最有价值的 50 个图表【译文】

###### Matplotlib

###### 下一页

#### Python 数据分析三剑客之 Matplotlib（九）：极区图/极坐标图/雷达图的绘制

###### Matplotlib 极区图 极坐标图 雷达图

#### 评论

## ๑۩ﺴ TRHX ﺴ۩๑

本文目录
欢迎光临

Hexo QQ 交流群 Telegram 交流群

CSDN 内容合伙人

文章分类

- BLOG
  (4)
- CDN
  (1)
- Hexo
  (9)
- Java
  (1)
- Linux
  (2)
- Markdown
  (2)
- Python 数据分析
  (27)
- Matplotlib
  (11)
- NumPy
  (6)
- Pandas
  (10)
- Python3 学习笔记
  (41)
- 基础学习
  (9)
- 学习经验
  (4)
- 爬虫学习
  (18)
- 爬虫实战
  (10)
- VPS
  (1)
- WEB前端
  (2)
- 图床
  (1)

热门标签
12306 3D图 58同城 Ajax BLOG Beautiful Soup CDN Coding Pages DataFrame Deepin Elicpse GitHub Pages Github Github Pages GroupBy HTTPS Hexo ICP备案 IO操作 Index JDBC JS 预加载 LaTeX Markdown Material X Matplotlib MongoDB MySQL NumPy PEP8 Pandas PicGo Pygame Python Redis SEO SQL Server 2012 SSR Selenium Series Ubuntu User-Agent VMware VPS XPath if语句 input()函数 instant.page jsDelivr lxml matplotibrc pyspider requests spfk urllib while循环 主题个性化 代理 位运算 公安备案 函数 函数应用 分割 切片 列表 判断函数 前程无忧 变量 合并数据集 哔哩哔哩 图例 图床 图形验证码 垃圾 备份 子图 字典 字符串函数 安居客 层级索引 年终总结 广播 异常 技巧 拼接 排序 排序函数 操作列表 散点图 数学函数 数据分裂 数据可视化 数据合并 数据替换 数据类型 数据读写 数据重塑 数组 文件 文件储存 无界面浏览器 时间序列 映射 条件函数 条形图 极区图 极坐标图 柱状图 模块 正则表达式 滑动验证码 点触验证码 爬虫 猫眼电影 瓜子二手车 画布 直方图 矩阵 等值线图 等高线图 算术函数 算术运算 类 索引 线性代数 线性图 统计函数 统计描述 统计计算 继承 编辑器 缺失值 网格 肺炎疫情 虎扑论坛 补丁 豆瓣电影 迭代 雷达图 饼状图
最近在听