如何在二维和三维投影之间切换

4 投票
3 回答
9619 浏览
提问于 2025-04-17 05:19

我有一个用matplotlib画的图,我想在2D和3D视图之间切换。我可以从2D切换到3D,但反过来就不行了。比如说...

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

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

fig = plt.figure()

# Create a 3D scatter plot...
ax = fig.add_subplot(111, projection='3d')
n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
    xs = randrange(n, 23, 32)
    ys = randrange(n, 0, 100)
    zs = randrange(n, zl, zh)
    ax.scatter(xs, ys, zs, c=c, marker=m)

ax.set_xlabel('X Label')
ax.set_ylabel('Y Label')
ax.set_zlabel('Z Label')

# Now I want a 2D plot...
ax.cla()
ax = fig.add_subplot(111)
ax.plot(xs, ys)

plt.show()

图形一直保持在3D视图,而projection="2D"这个参数似乎不被认可...

我想也许ax.clf()可以帮我实现这个目标,让我重新定义一个新的图形。但结果却出现了以下错误: ValueError: Unknown element o

有没有人能给我一点提示,怎么解决这个问题?这个ValueError是跟我遇到的问题有关,还是暗示我的设置有其他问题?有没有什么参数可以用来把视图从3D切换回2D呢?

3 个回答

1

我之前也遇到过同样的问题,试了Dan提供的解决办法。这个办法有效,但给我提示了一个警告:

“用户警告:这个图形包含了一些与紧凑布局不兼容的坐标轴,所以结果可能不正确。”

不过如果我使用:

self.figure.clf()
self.axes = self.figure.add_subplot(111)

那么就没有任何警告了,效果很好。

2

首先,我想说的是,如果你能提高你的接受率(目前是0%),比如把你之前问题中用过的答案标记出来,可能会有更多人愿意帮助你。

现在,关于你的问题,实际上没有“2d”这个投影的选项。不过,如果你想快速决定想要哪种类型的投影,可以根据一个叫“q”的关键词来选择,下面的内容应该能帮到你。我还调整了一下基本的设置,以避免你不同类型的图表之间产生混淆,因为你在循环外有一些绘图的调用,同时也让你的代码结构更清晰。

希望这对你有帮助。

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

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

fig = plt.figure()
plt.clf()

q='2d'

n = 100
for c, m, zl, zh in [('r', 'o', -50, -25), ('b', '^', -30, -5)]:
  xs = randrange(n, 23, 32)
  ys = randrange(n, 0, 100)  
  zs = randrange(n, zl, zh)

if q=='3d':

  # Create a 3D scatter plot...
  ax = fig.add_subplot(111, projection='3d')
  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()

else:
  plt.clf()
  ax = fig.add_subplot(111)
  ax.plot(xs, ys)
  ax.set_xlabel('X Label')
  ax.set_ylabel('Y Label')
  plt.show()
1

我觉得我找到了一种可能的解决办法,不过这似乎会导致一些内存问题。我怀疑它并没有真正删除最开始的图表数据,只是把它从图形中移除了,所以每次改变投影的时候,内存使用量都会增加。

# Delete the 3D subplot
self.fig.delaxes(self.axes)
# Create a new subplot that is 2D
self.axes = self.fig.add_subplot(111)
# 2D scatter
self.axes.plot(10*np.random.randn(100), 10*np.random.randn(100), 'o')
# Update the figure
self.canvas.draw()

撰写回答