You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Matplotlib的3D绘图中绘制多条分离折线

解决3D绘图中按X值分组绘制多条折线的问题

哈哈,这个场景我太熟悉了!你直接用ax.plot3D(xs,ys,zs)会把所有点按顺序连起来,自然没法得到每条x固定的独立折线。核心思路就是先把数据按xs的唯一值分组,然后每组单独调用plot3D绘制,下面给你两种实用的实现方法:

方法一:用itertools.groupby(适合数据已按X排序的情况)

你的xs是已经按相同值连续排列的([1,1,1,2,2,2,3,3,3]),刚好可以直接用groupby按x值分组:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from itertools import groupby

# 定义你的数据
xs = [1,1,1,2,2,2,3,3,3]
ys = [1,2,3,1,2,3,1,2,3]
zs = [1,4,9,2,8,18,4,16,36]

# 创建3D绘图轴
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 把三个列表打包成(x,y,z)元组,按x值分组
data = list(zip(xs, ys, zs))
for x_val, group in groupby(data, key=lambda item: item[0]):
    # 提取当前x值对应的y和z数据
    group_ys = [item[1] for item in group]
    group_zs = [item[2] for item in group]
    # 生成和y/z长度一致的x列表(全是当前x_val)
    group_xs = [x_val] * len(group_ys)
    # 绘制这一组的折线
    ax.plot3D(group_xs, group_ys, group_zs, label=f'x={x_val}')

# 添加标签和图例,让图更清晰
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
ax.legend()

plt.show()

如果你的xs不是有序排列的,记得先给数据按x值排序,再用groupby:

data_sorted = sorted(data, key=lambda item: item[0])
for x_val, group in groupby(data_sorted, key=lambda item: item[0]):
    # 后面的代码和上面一样

方法二:用Numpy筛选(更通用,无需考虑数据顺序)

如果你习惯用Numpy处理数据,这种方法更直观,不管xs是不是有序的都能直接用:

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

# 定义数据并转成Numpy数组
xs = np.array([1,1,1,2,2,2,3,3,3])
ys = np.array([1,2,3,1,2,3,1,2,3])
zs = np.array([1,4,9,2,8,18,4,16,36])

# 创建3D绘图轴
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 获取xs的所有唯一值
unique_x_values = np.unique(xs)

# 循环每个唯一x值,筛选对应的y和z并绘制
for x_val in unique_x_values:
    # 生成筛选掩码:找到所有x等于x_val的位置
    mask = xs == x_val
    # 提取对应的数据
    filtered_y = ys[mask]
    filtered_z = zs[mask]
    # 生成对应长度的x数组
    filtered_x = np.full_like(filtered_y, x_val)
    # 绘制折线
    ax.plot3D(filtered_x, filtered_y, filtered_z, label=f'x={x_val}')

# 添加标签和图例
ax.set_xlabel('X Axis')
ax.set_ylabel('Y Axis')
ax.set_zlabel('Z Axis')
ax.legend()

plt.show()

这两种方法都能实现你要的效果:每个x的唯一值对应一条独立的3D折线,不会把所有点连成一条线。你可以根据自己的代码习惯选一种就行~

内容的提问来源于stack exchange,提问作者Nightshade

火山引擎 最新活动