数据可视化就是这样一个领域,其中大量库已经用 Python 开发。
其中,Matplotlib是数据可视化最受欢迎的选择,那么Python如何画3D图呢?
虽然最初开发用于绘制直方图、条形图、散点图、折线图等 2-D 图表,但 Matplotlib 已扩展其功能以提供 3D 绘图模块。
在本Python matplotlib三维绘图教程中,我们将了解 Python 中 3D 绘图的各个方面。
Python如何画三维图?我们将首先在 3D 坐标空间中绘制一个点。然后我们将学习如何自定义我们的绘图,然后我们将继续学习更复杂的绘图,如 3D 高斯曲面、3D 多边形等。 具体来说,我们将研究以下主题:
matplotlib如何3D绘图?教程目录如下
- 在 3D 空间中绘制单个点
- 第 1 步:导入库
- 第 2 步:创建图形和轴
- 第 3 步:绘制点
- 绘制 3D 连续线
- 自定义 3D 绘图
- 添加标题
- 添加轴标签
- 修改标记
- 修改轴限制和刻度
- 改变图的大小
- 关闭/打开网格线
- 根据类设置 3D 绘图颜色
- 放置传奇
- 不同大小的绘图标记
- 绘制高斯分布
- 绘制 3D 多边形
- 用鼠标旋转 3D 绘图
- 绘制两个不同的 3D 分布
- 将 Python 3D 绘图输出到 HTML
- 结论
Python 3D图绘制:在 3D 空间中绘制单个点
Python如何画3D图?让我们首先完成在 Python 中创建 3D 绘图所需的每个步骤,并举一个在 3D 空间中绘制点的示例。
第 1 步:导入库
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
第一个是使用 matplotlib 进行绘图的标准导入语句,您也会在 2D 绘图中看到它。 启用 3D 投影需要该类
的第二次导入 Axes3D
。否则,它不会在其他任何地方使用。
请注意,3.2.0 之前的 Matplotlib 版本需要第二次导入。对于 3.2.0 及更高版本,您无需导入 mpl_toolkits.mplot3d.Axes3D
.
第 2 步:创建图形和轴
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, projection='3d')
输出:
这里我们首先创建一个大小为 4 英寸 X 4 英寸的图形。
然后,我们通过调用该add_subplot
方法并将值 '3d' 指定给projection
参数来 创建一个 3-D 轴对象 。
我们将使用这个轴对象 'ax' 向图中添加任何绘图。
请注意,这两个步骤在您使用 Matplotlib 在 Python 中进行的大多数 3D 绘图中很常见。
第 3 步:绘制点
创建轴对象后,我们可以使用它在 3D 空间中创建我们想要的任何类型的绘图。
要绘制单个点,我们将使用 scatter()
方法,并传递该点的三个坐标。
fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(2,3,4) # plot the point (2,3,4) on the figure
plt.show()
输出:
如您所见,在 (2,3,4) 处绘制了一个点(蓝色)。
Python matplotlib三维绘图:绘制 3D 连续线
现在我们知道如何在 3D 中绘制单个点,我们可以类似地绘制一条穿过 3D 坐标列表的连续线。
我们将使用该 plot()
方法并传递 3 个数组,每个数组一个用于在线上点的 x、y 和 z 坐标。
import numpy as np
x = np.linspace(−4*np.pi,4*np.pi,50)
y = np.linspace(−4*np.pi,4*np.pi,50)
z = x**2 + y**2
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(x,y,z)
plt.show()
输出:
我们正在为 50 个点生成 x、y 和 z 坐标。
x 和 y 坐标使用 np.linspace
生成 -4π 和 +4π 之间的 50 个均匀分布的点。z 坐标只是相应的 x 和 y 坐标的平方和。
Python如何画三维图?自定义 3D 绘图
让我们在 3D 空间中绘制一个散点图,看看我们如何根据我们的喜好以不同的方式自定义其外观。我们将使用NumPy 随机种子,因此您可以生成与教程相同的随机数。
np.random.seed(42)
xs = np.random.random(100)*10+20
ys = np.random.random(100)*5+7
zs = np.random.random(100)*15+50
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs,ys,zs)
plt.show()
输出:
现在让我们为这个图添加一个标题
添加标题
我们将调用set_title
轴对象的 方法为绘图添加标题。
ax.set_title("Atom velocity distribution")
plt.show()
输出:
注意,我没有在此处添加前面的代码(用于创建图形并添加散点图),但您应该这样做。
现在让我们为图中的每个轴添加标签。
添加轴标签
我们可以通过调用方法设置在3D绘图每个轴一个标签 set_xlabel
, set_ylabel
和 set_zlabel
轴对象。
ax.set_xlabel("Atomic mass (dalton)")
ax.set_ylabel("Atomic radius (pm)")
ax.set_zlabel("Atomic velocity (x10⁶ m/s)")
plt.show()
输出:
matplotlib如何3D绘图:修改标记
正如我们在前面的例子中看到的,默认情况下,每个点的标记是一个固定大小的蓝色实心圆圈。
我们可以改变标记的外观,使它们更具表现力。
让我们从改变标记的颜色和样式开始
ax.scatter(xs,ys,zs, marker="x", c="red")
plt.show()
输出:
我们使用了参数 marker
并 c
改变了各个点的样式和颜色
修改轴限制和刻度
Python如何画3D图?默认情况下,根据输入值设置轴上值的范围和间隔。
然而,我们可以将它们更改为我们想要的值。
让我们创建另一个表示一组新数据点的散点图,然后修改其轴范围和间隔。
np.random.seed(42)
ages = np.random.randint(low = 8, high = 30, size=35)
heights = np.random.randint(130, 195, 35)
weights = np.random.randint(30, 160, 35)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs = heights, ys = weights, zs = ages)
ax.set_title("Age-wise body weight-height distribution")
ax.set_xlabel("Height (cm)")
ax.set_ylabel("Weight (kg)")
ax.set_zlabel("Age (years)")
plt.show()
输出:
我们在 3 个轴上绘制了 3 个变量的数据,即身高、体重和年龄。
如您所见,X、Y 和 Z 轴上的限制已根据输入数据自动分配。
让我们修改的最小和最大限制在每个轴上,通过调用 set_xlim
, set_ylim
和 set_zlim
方法。
ax.set_xlim(100,200)
ax.set_ylim(20,160)
ax.set_zlim(5,35)
plt.show()
输出:
三个轴的限制已根据我们传递给相应方法的最小值和最大值进行了修改。
我们还可以修改每个轴的单个刻度。目前,X 轴刻度为 [100,120,140,160,180,200]。
让我们将其更新为 [100,125,150,175,200]
ax.set_xticks([100,125,150,175,200])
plt.show()
输出:
类似地,我们可以使用set_yticks
和 set_zticks
方法更新 Y 和 Z 刻度 。
ax.set_yticks([20,55,90,125,160])
ax.set_zticks([5,15,25,35])
plt.show()
输出:
Python 3D图绘制:改变图的大小
Python matplotlib三维绘图:如果我们希望我们的绘图比默认大小更大或更小,我们可以在初始化图形时轻松设置绘图的大小 - 使用 方法的 figsize
参数 plt.figure
,
或者我们可以通过调用更新现有绘图的大小 set_size_inches
图对象上的方法。
在这两种方法中,我们必须以英寸为单位指定绘图的宽度和高度。
由于我们之前已经看到了指定绘图大小的第一种方法,现在让我们看看第二种方法,即修改现有绘图的大小。
我们将散点图的大小更改为 6×6 英寸。
fig.set_size_inches(6, 6)
plt.show()
输出:
与之前的默认大小相比,散点图的大小有所增加。
关闭/打开网格线
到目前为止,我们绘制的所有图都默认带有网格线。
我们可以通过调用grid
轴对象的方法来改变这一点 ,并传递值 'False'。
如果我们想要网格线再次返回,我们可以使用参数 'True.' 调用相同的方法。
ax.grid(False)
plt.show()
输出:
根据类设置 3D 绘图颜色
让我们假设散点图所代表的个体被进一步分为两个或更多类别。
我们可以通过用不同颜色绘制每个类别的个体来表示这些信息。
例如,让我们将数据分为“男性”和“女性”类别。
我们将创建一个与数据点数量相同大小的新数组,并为“男性”类别分配值 0,为“女性”类别分配值 1。
然后,我们将c
在创建散点图时将此数组传递给颜色参数 。
np.random.seed(42)
ages = np.random.randint(low = 8, high = 30, size=35)
heights = np.random.randint(130, 195, 35)
weights = np.random.randint(30, 160, 35)
gender_labels = np.random.choice([0, 1], 35) #0 for male, 1 for female
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs = heights, ys = weights, zs = ages, c=gender_labels)
ax.set_title("Age-wise body weight-height distribution")
ax.set_xlabel("Height (cm)")
ax.set_ylabel("Weight (kg)")
ax.set_zlabel("Age (years)")
plt.show()
输出:
该图现在用不同的颜色显示两个类别中的每一个。
但是我们怎么知道哪种颜色对应哪个类别呢?
我们可以添加一个'colorbar'来解决这个问题。
scat_plot = ax.scatter(xs = heights, ys = weights, zs = ages, c=gender_labels)
cb = plt.colorbar(scat_plot, pad=0.2)
cb.set_ticks([0,1])
cb.set_ticklabels(["Male", "Female"])
plt.show()
输出:
放置传奇
通常我们有超过 1 组数据要绘制在同一个图上。
在这种情况下,我们必须为每个图分配标签并在图中添加图例以区分不同的图。
Python如何画3D图?例如,让我们假设我们的年龄-身高-体重数据是从美国的 3 个州收集的,即佛罗里达州、乔治亚州和加利福尼亚州。
我们想为这 3 个状态绘制散点图并添加一个图例来区分它们。
让我们在 for 循环中创建 3 个图,并每次为它们分配不同的标签。
labels = ["Florida", "Georgia", "California"]
for l in labels:
ages = np.random.randint(low = 8, high = 20, size=20)
heights = np.random.randint(130, 195, 20)
weights = np.random.randint(30, 160, 20)
ax.scatter(xs = heights, ys = weights, zs = ages, label=l)
ax.set_title("Age-wise body weight-height distribution")
ax.set_xlabel("Height (cm)")
ax.set_ylabel("Weight (kg)")
ax.set_zlabel("Age (years)")
ax.legend(loc="best")
plt.show()
输出:
不同大小的绘图标记
在我们目前看到的散点图中,所有点标记的大小都是恒定的。
我们可以通过将自定义值传递给s
散点图的参数来改变标记的大小 。
我们可以传递一个数字来将所有标记设置为一个新的固定大小,或者我们可以提供一个值数组,其中每个值代表一个标记的大小。
Python如何画三维图?在我们的示例中,我们将根据个体的身高和体重计算一个名为“bmi”的新变量,并使个体标记的大小与其 BMI 值成正比。
np.random.seed(42)
ages = np.random.randint(low = 8, high = 30, size=35)
heights = np.random.randint(130, 195, 35)
weights = np.random.randint(30, 160, 35)
bmi = weights/((heights*0.01)**2)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs = heights, ys = weights, zs = ages, s=bmi*5 )
ax.set_title("Age-wise body weight-height distribution")
ax.set_xlabel("Height (cm)")
ax.set_ylabel("Weight (kg)")
ax.set_zlabel("Age (years)")
plt.show()
输出:
该图中标记的大小越大,这些个体的 BMI 越高,反之亦然。
matplotlib如何3D绘图?绘制高斯分布
Python matplotlib三维绘图:您可能知道绘制在二维平面上的单变量高斯分布,通常称为“钟形曲线”。
来源:https : //en.wikipedia.org/wiki/File : Normal_Distribution_PDF.svg
我们还可以使用多元正态分布在 3D 空间中绘制高斯分布。
我们必须定义变量 X 和 Y,并一起绘制它们的概率分布。
from scipy.stats import multivariate_normal
X = np.linspace(-5,5,50)
Y = np.linspace(-5,5,50)
X, Y = np.meshgrid(X,Y)
X_mean = 0; Y_mean = 0
X_var = 5; Y_var = 8
pos = np.empty(X.shape+(2,))
pos[:,:,0]=X
pos[:,:,1]=Y
rv = multivariate_normal([X_mean, Y_mean],[[X_var, 0], [0, Y_var]])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, rv.pdf(pos), cmap="plasma")
plt.show()
输出:
使用该
plot_surface
方法,我们可以在 3D 空间中创建相似的表面。
绘制 3D 多边形
我们还可以在 Python 中绘制具有 3 维顶点的多边形。
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
x = [1, 0, 3, 4]
y = [0, 5, 5, 1]
z = [1, 3, 4, 0]
vertices = [list(zip(x,y,z))]
poly = Poly3DCollection(vertices, alpha=0.8)
ax.add_collection3d(poly)
ax.set_xlim(0,5)
ax.set_ylim(0,5)
ax.set_zlim(0,5)
输出:
Python 3D图绘制:用鼠标旋转 3D 绘图
要在Jupyter Notebook 中创建交互式绘图,您应该在Notebook 的开头运行
magic 命令 %matplotlib notebook
。
这使我们能够通过放大和缩小绘图以及向任何方向旋转它们来与 3D 绘图进行交互。
%matplotlib notebook
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.stats import multivariate_normal
X = np.linspace(-5,5,50)
Y = np.linspace(-5,5,50)
X, Y = np.meshgrid(X,Y)
X_mean = 0; Y_mean = 0
X_var = 5; Y_var = 8
pos = np.empty(X.shape+(2,))
pos[:,:,0]=X
pos[:,:,1]=Y
rv = multivariate_normal([X_mean, Y_mean],[[X_var, 0], [0, Y_var]])
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, rv.pdf(pos), cmap="plasma")
plt.show()
输出:
Python如何画三维图?绘制两个不同的 3D 分布
借助该fig.add_subplot
方法,我们可以将两个不同的 3D 绘图添加到同一个图形中 。
我们提供给该方法的 3 位数字表示网格中的行数和列数以及当前绘图在网格中的位置。
前两位数字表示我们需要划分图形的总行数和列数。
最后一位数字表示子图在网格中的位置。
Python如何画3D图?例如,如果我们将值 223 传递给该 add_subplot
方法,我们指的是 2×2 网格中的第三个图(考虑行优先排序)。
现在让我们看一个例子,我们在一个图上绘制两个不同的分布。
#data generation for 1st plot
np.random.seed(42)
xs = np.random.random(100)*10+20
ys = np.random.random(100)*5+7
zs = np.random.random(100)*15+50
#data generation for 2nd plot
np.random.seed(42)
ages = np.random.randint(low = 8, high = 30, size=35)
heights = np.random.randint(130, 195, 35)
weights = np.random.randint(30, 160, 35)
fig = plt.figure(figsize=(8,4))
#First plot
ax = fig.add_subplot(121, projection='3d')
ax.scatter(xs,ys,zs, marker="x", c="red")
ax.set_title("Atom velocity distribution")
ax.set_xlabel("Atomic mass (dalton)")
ax.set_ylabel("Atomic radius (pm)")
ax.set_zlabel("Atomic velocity (x10⁶ m/s)")
#Second plot
ax = fig.add_subplot(122, projection='3d')
ax.scatter(xs = heights, ys = weights, zs = ages)
ax.set_title("Age-wise body weight-height distribution")
ax.set_xlabel("Height (cm)")
ax.set_ylabel("Weight (kg)")
ax.set_zlabel("Age (years)")
plt.show()
输出:
我们可以通过这种方式绘制任意数量的子图,只要我们将它们放在网格中即可。
将 Python 3D 绘图输出到 HTML
matplotlib如何3D绘图?如果我们想将一个 3D 绘图图形嵌入到 HTML 页面中,而无需先将其保存为图像文件,
我们可以通过将图形编码为“base64”,然后将其插入 HTMLimg
标签中的正确位置来实现
import base64
from io import BytesIO
np.random.seed(42)
xs = np.random.random(100)*10+20
ys = np.random.random(100)*5+7
zs = np.random.random(100)*15+50
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter(xs,ys,zs)
#encode the figure
temp = BytesIO()
fig.savefig(temp, format="png")
fig_encode_bs64 = base64.b64encode(temp.getvalue()).decode('utf-8')
html_string = """
<h2>This is a test html</h2>
<img src = 'data:image/png;base64,{}'/>
""".format(fig_encode_bs64)
我们现在可以将这个 HTML 代码字符串写入一个 html 文件,然后我们可以在浏览器中查看
with open("test.html", "w") as f:
f.write(html_string)
输出:
Python matplotlib三维绘图总结
Python如何画三维图?在本教程中,我们学习了如何使用 matplotlib 库在 Python 中绘制 3D 图。
我们首先在 3D 坐标空间中绘制一个点,然后绘制 3D 曲线和散点图。
然后我们学习了在 Python 中自定义 3D 绘图的各种方法,例如向绘图添加标题、图例、轴标签、调整绘图大小、打开/关闭绘图上的网格线、修改轴刻度等。
我们还学习了如何根据数据点类别改变标记的大小和颜色。
Python 3D图绘制:之后,我们学习了如何在 3D 空间中绘制曲面。我们在 Python 中绘制了一个高斯分布和一个 3D 多边形。
然后我们看到了如何在 Jupyter notebook 中与 Python 3D 绘图进行交互。
最后,我们学习了如何在同一个图形上绘制多个子图,以及如何将图形输出到 HTML 代码中。