import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d.art3d import Poly3DCollection # 生成数据 Round = np.array([0, 1, 2]) # 横轴 Round A1 = np.array([2, 4, 6, 8]) # 纵轴 A1 Z = np.array([ [17.1, 22.3, 23.8, 24.1], [14.5, 19.0,20.4, 20.9], [11.8, 15.1, 16.7, 17.3] ]) # 创建图形 X, Y = np.meshgrid(A1, Round) fig = plt.figure(figsize=(8, 6)) ax = fig.add_subplot(111, projection='3d') # 绘制3D曲面 for i in range(Z.shape[0]): # 绘制每个数据线条,并标注关键点 ax.plot(Y[i], X[i], Z[i], '-o') ax.plot(Y[i], X[i], np.zeros_like(Z[i]), color='gray', alpha=0.5) # 填充每个四边形面 for j in range(len(A1) - 1): verts = [ [Y[i, j], X[i, j], 0], [Y[i, j + 1], X[i, j + 1], 0], [Y[i, j + 1], X[i, j + 1], Z[i, j + 1]], [Y[i, j], X[i, j], Z[i, j]] ] ax.add_collection3d(Poly3DCollection([verts], color=plt.cm.viridis(i / len(Round)), alpha=0.4)) # 在每个关键点上添加注释 for j in range(Z.shape[1]): ax.text(Y[i, j], X[i, j], Z[i, j] + 0.03, f'{Z[i, j]:.2f}', color='black', ha='center') # 绘制每个点之间的连接线 for j in range(Z.shape[1]): ax.plot(Y[:, j], X[:, j], Z[:, j], '--', color='gray') # 设置标签 ax.set_xlabel('Round') ax.set_ylabel('A1') ax.set_zlabel('Cooperation Rate') # 显示图像 plt.show() # 绘制无直线3D瀑布图 import matplotlib.pyplot as plt import matplotlib.ticker as ticker from mpl_toolkits.mplot3d.art3d import Poly3DCollection import numpy as np def line_3d(x, y, z, x_label_indexs): """ 在y轴的每个点,向x轴的方向延伸出一个折线面:展示每个变量的时序变化。 x: x轴,时间维,右边。 y: y轴,变量维,左边。 z: z轴,数值维。二维矩阵,y列x行。每一行是对应变量的一个时间序列。 x_label_indexs: 需要标注的时间点。 """ x_num = len(x) y_num = len(y) if z.shape[0] != y_num or z.shape[1] != x_num: return -1 # 制作坐标格点(z中每个点对应的x、y坐标) X, Y = np.meshgrid(x, y) # 初始化 canvas = plt.figure() # 创建画布 axs = canvas.add_subplot(111, projection='3d') # 添加三维子图 # 若把111改成234,则意思是:创建一个2*3的网格,并在第4个格子中创建一个axes # 绘制折线面
时间: 2025-06-16 07:49:46 浏览: 24
<think>嗯,用户想用Matplotlib和NumPy绘制包含注释、填充表面、连接线的3D图表,还要实现无直线3D瀑布图。首先,我需要回忆Matplotlib中3D绘图的相关知识。记得Axes3D是处理3D图的关键模块,可能需要从mpl_toolkits.mplot3d导入。然后,用户提到的带注释的关键点,应该用annotate函数,但3D中的注释可能需要处理坐标转换。填充四边形面的话,可能需要使用plot_surface或者Poly3DCollection,但如果是四边形,可能需要定义顶点然后填充。连接线的话,应该是用plot函数在3D坐标系中绘制线条。
关于无直线3D瀑布图,通常瀑布图每个数据点之间有连线,但用户想要无直线,可能是指去掉线,只保留点或者面?或者可能是指另一种形式的表示,比如用柱状图或面片。不过通常3D瀑布图是线图,所以无直线可能需要用其他方式呈现,比如散点图或者填充面。或者可能是每个数据点独立,不连接,这样在绘制时就不画线。
现在需要考虑示例代码的结构。首先导入必要的库,比如numpy和matplotlib.pyplot,以及Axes3D。然后生成数据,比如用numpy的meshgrid创建X、Y、Z。对于填充四边形面,可能需要定义四边形的四个顶点,用Poly3DCollection来绘制,并设置颜色和透明度。连接线的话,用plot3D函数绘制线段。注释的话,用annotate,但要注意3D坐标到2D屏幕坐标的转换,可能要用proj3d.transform或者一些转换方法。
对于瀑布图,如果用户不要直线,可能需要使用bar3d来绘制柱状图,或者用plot_surface但设置线条不可见。例如,设置linewidth=0,或者用scatter绘制点。或者,如果是时间序列的多个曲线堆叠在3D中,可能需要每个曲线之间没有连接线,只显示填充的面。
另外,需要参考用户提供的引用内容。引用[1]提到了3D柱状图的绘制方法,使用bar3d函数,参数包括x、y坐标,底面高度、宽度、深度和高度。引用[2]涉及Matplotlib的基本使用和子图设置。引用[5]展示了堆积条形图的代码,可能对填充部分有参考价值。
可能需要分步骤编写代码。首先是创建3D坐标系的子图,然后生成数据。例如,生成一个曲面,或者一些离散点。然后添加注释,可能需要使用annotate,并调整位置。填充四边形的话,可能需要定义一个四边形,用Poly3DCollection添加到图中。连接线的话,用plot3D连接不同的点。对于瀑布图,可能需要多个曲线沿着某个轴排列,每个曲线之间填充颜色,但不绘制连接线。
对于无直线瀑布图,可能需要使用plot_surface,并设置线条样式为无,比如linewidth=0,或者用其他方式如contourf。或者,使用bar3d来绘制柱状,这样每个柱子独立,没有连接线。例如,沿Y轴排列多个X-Z平面的柱状图,形成瀑布效果。
现在需要整合这些思路,写出示例代码。例如:
1. 导入库:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
2. 创建数据:
生成X、Y网格,然后计算Z值,比如一个波浪形曲面。
3. 绘制注释点:
在某个坐标点处添加文字注释,例如在(x,y,z)位置标注“关键点”。
4. 填充四边形面:
创建一个四边形,定义四个顶点,使用Poly3DCollection填充颜色。
5. 连接线:
用plot连接两个点,形成线条。
6. 瀑布图部分:
生成多个Y值的曲线,每个曲线绘制在X-Z平面,沿Y轴排列,使用plot_surface或plot,但调整参数使线条不可见,填充颜色。
可能需要测试各个部分是否能正确运行,并确保注释的位置正确,四边形正确显示,连接线可见,瀑布图无直线。
需要注意,Poly3DCollection需要顶点坐标的正确排列,可能每个四边形由四个顶点组成,作为列表传入。而annotate在3D中可能需要使用text方法,因为annotate可能在2D坐标系,但text3D可以处理三维坐标,但Matplotlib的text函数支持三维坐标。
另外,瀑布图的实现可能需要将多个2D曲线沿着第三个轴堆叠,每个曲线使用fill_between填充,并在3D中提升到对应的Y位置。这样,每个曲线之间没有连接线,只有填充的面,形成瀑布效果。例如,循环生成不同Y值的曲线,对每个曲线计算Z值,并绘制填充区域,同时提升到对应的Y位置。
总结步骤:
1. 基础3D图表结构(导入、创建子图)
2. 注释关键点(使用text或annotate)
3. 填充四边形(Poly3DCollection)
4. 连接线(plot3D)
5. 瀑布图:生成多组数据,沿Y轴排列,绘制填充面,关闭线条
然后根据这些步骤编写代码,并解释各部分的作用。可能需要多次调整参数,例如颜色、透明度、视角等,以确保图表清晰。</think>以下是使用Matplotlib和NumPy绘制3D图表及实现无直线瀑布图的代码解析:
### 一、基础3D图表结构搭建
```python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
fig = plt.figure(figsize=(16, 8))
ax = fig.add_subplot(121, projection='3d') # 创建3D坐标系
```
### 二、带注释关键点实现
```python
# 生成数据点
x = np.array([1, 3, 5])
y = np.array([2, 4, 6])
z = np.array([0, 2, 1])
# 绘制关键点
ax.scatter(x, y, z, c='r', s=50)
# 添加文字注释(支持三维坐标)
for i in range(len(x)):
ax.text(x[i], y[i], z[i]+0.3, f'Point {i+1}', color='blue', fontsize=8)
```
### 三、填充四边形面实现
```python
# 定义四边形顶点坐标(四个点需共面)
verts = [(1,2,0), (3,4,2), (5,6,1), (2,3,1.5)]
quad = [verts]
# 创建多边形集合对象
quad_collection = Poly3DCollection(quad, alpha=0.3, facecolors='cyan')
ax.add_collection3d(quad_collection)
# 绘制四边形边线
ax.plot3D(*zip(*verts + [verts[0]]), color='black', linestyle='--')
```
### 四、连接线绘制
```python
# 绘制三维线段(连接点0和点2)
ax.plot3D([x[0], x[2]], [y[0], y[2]], [z[0], z[2]],
linewidth=2, color='green', marker='o')
```
### 五、无直线3D瀑布图实现
```python
# 生成瀑布数据
ax2 = fig.add_subplot(122, projection='3d')
y_wf = np.arange(0, 5, 0.5)
x_wf = np.linspace(-3, 3, 50)
for yi in y_wf:
z_wf = np.sin(x_wf) * np.cos(yi)
# 填充区域(关键参数:关闭线条)
ax2.fill_between(x_wf, z_wf, -1,
where=z_wf > -1,
facecolor=plt.cm.viridis(yi/5),
alpha=0.7,
edgecolor='none') # 关闭边线
# 提升到对应y轴高度
ax2.add_collection3d(
Poly3DCollection([list(zip(x_wf, [yi]*len(x_wf), z_wf))],
facecolors=plt.cm.viridis(yi/5),
alpha=0.7))
```
### 六、图表参数设置
```python
# 设置观察角度
ax.view_init(elev=25, azim=-45)
ax2.view_init(elev=15, azim=60)
# 设置坐标轴标签
for axis in [ax, ax2]:
axis.set_xlabel('X Axis')
axis.set_ylabel('Y Axis')
axis.set_zlabel('Z Axis')
plt.tight_layout()
plt.show()
```
### 关键参数解析
1. **注释定位**:`text()`方法直接支持三维坐标定位,比`annotate()`更适合3D场景[^2]
2. **面片填充**:使用`Poly3DCollection`时需要提供顶点列表,每个面片由多个多边形组成[^1]
3. **瀑布图核心**:
- 通过`fill_between`创建二维填充区域
- 使用`add_collection3d`将二维图形提升到三维空间
- `edgecolor='none'`消除连接线[^5]
### 效果说明
左图展示带注释点、四边形面和连接线的复合3D图形,右图实现基于面片填充的无直线瀑布图。通过调整`facecolors`参数可修改颜色映射方案,修改`alpha`值控制透明度[^3]。
阅读全文
相关推荐


















