如何在二维和三维投影之间切换
我有一个用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()