为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法在 matplotlib 中标记多个 3d 表面?

有没有办法在 matplotlib 中标记多个 3d 表面?

斯蒂芬大帝 2021-12-29 20:18:32
我试图用线性约束解决非线性数学优化问题。为此,我试图在 3d 中可视化约束以查看发生了什么以及为什么我得到了约束中某些参数而不是其他参数的可行解决方案。为了实现这一点,我想使用python 中的matplotlib来生成 3d 表面(平面,因为我的所有约束都是线性的)。但是,如果没有图内标记,则很难确定哪个曲面属于哪个约束。这让我想寻找一种方法来在情节内添加带有颜色的图例。我认识到已经有一种方法可以在 2D 中执行此操作,在方法中ax.plot()或 中ax.scatter(),但尝试执行相同操作并不起作用ax.plot_surface(X, Y, Z, label = 'mylabel')完整脚本如下:from mpl_toolkits import mplot3dfrom mpl_toolkits.mplot3d import Axes3Dimport matplotlib.pyplot as pltimport numpy as npfig = plt.figure()ax = plt.axes(projection='3d')plt.rcParams['legend.fontsize'] = 10# First constraintg2 = np.linspace(-5,5,2)g3 = np.linspace(-5,5,2)G2,G3 = np.meshgrid(g2,g3)G4_1 = -1.18301270189222 - 0.5*G2 + 0.5*G3ax = fig.gca(projection='3d')c1 = ax.plot_surface(G2, G3, G4_1, label = "c1")# SecondG3, G4 = np.meshgrid(g2, g3)G2 = G3c2 = ax.plot_surface(G2, G3, G4, label = "c2")# ThirdG2,G3 = np.meshgrid(g2,g3)G4 = (0.408248290463863*G2 + 0.408248290463863*G3 -0.707106781186548)/1.63299316185545c3 = ax.plot_surface(G2, G3, G4, label = "c3")# And forthG4 = (1.04903810567666 - (0.288675134594813*G2 + 0.288675134594813*G3))/0.577350269189626c4 = ax.plot_surface(G2, G3, G4, label="c4")ax.legend() # -> error : 'AttributeError: 'Poly3DCollection' object has no attribute '_edgecolors2d''# labeling the figurefig.suptitle("Constraints")#plt.xlabel('g2', fontsize=14)#plt.ylabel('g3', fontsize=14)ax.set_xlabel(r'$g_2$', fontsize=15, rotation=60)ax.set_ylabel('$g_3$', fontsize=15, rotation=60)ax.set_zlabel('$g_4$', fontsize=15, rotation=60)plt.savefig('Constraints.jpg')plt.show()结果如下图。正如您可能已经看到的那样,无法分辨哪个表面属于哪个约束,而我想要实现的是一个图例,就像这里。我通读了这个问题的答案,但它在这里不起作用,因为我有多个表面。尝试之后,它一直只显示一个标签,而不是四个。所以我的问题是,有没有办法为我的ax.plot_surface或任何其他合适的黑客添加图例?
查看完整描述

2 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

你去吧。


解决方案是这里的错误:ax.legend() # -> error : 'AttributeError: 'Poly3DCollection' object has no attribute '_edgecolors2d''。

我相信这是一个错误。


如果您探索任何表面对象(比如c1),您可以看到它们具有属性'_edgecolors3d',这是创建图例时应调用的属性。


因此,我们只需创建一个新属性,其名称'_edgecolors2d'与'_edgecolors3d'.


一旦'_edgecolors2d'问题解决,你会遇到一个新的使用'_facecolors2d'。我们重复相同的程序,我们就完成了。



fig = plt.figure()

ax = plt.axes(projection='3d')


plt.rcParams['legend.fontsize'] = 10



# First constraint

g2 = np.linspace(-5,5,2)

g3 = np.linspace(-5,5,2)

G2,G3 = np.meshgrid(g2,g3)

G4_1 = -1.18301270189222 - 0.5*G2 + 0.5*G3

ax = fig.gca(projection='3d')

c1 = ax.plot_surface(G2, G3, G4_1, label = "c1")

c1._facecolors2d=c1._facecolors3d

c1._edgecolors2d=c1._edgecolors3d


# Second

G3, G4 = np.meshgrid(g2, g3)

G2 = G3

c2 = ax.plot_surface(G2, G3, G4, label = "c2")

c2._facecolors2d=c2._facecolors3d

c2._edgecolors2d=c2._edgecolors3d


# Third

G2,G3 = np.meshgrid(g2,g3)

G4 = (0.408248290463863*G2 + 0.408248290463863*G3 -0.707106781186548)/1.63299316185545

c3 = ax.plot_surface(G2, G3, G4, label = "c3")

c3._facecolors2d=c3._facecolors3d

c3._edgecolors2d=c3._edgecolors3d


# And forth

G4 = (1.04903810567666 - (0.288675134594813*G2 + 0.288675134594813*G3))/0.577350269189626

c4 = ax.plot_surface(G2, G3, G4, label="c4")


c4._facecolors2d=c4._facecolors3d

c4._edgecolors2d=c4._edgecolors3d


ax.legend() # -> error : 'AttributeError: 'Poly3DCollection' object has no attribute '_edgecolors2d''



# labeling the figure

fig.suptitle("Constraints")

#plt.xlabel('g2', fontsize=14)

#plt.ylabel('g3', fontsize=14)

ax.set_xlabel(r'$g_2$', fontsize=15, rotation=60)

ax.set_ylabel('$g_3$', fontsize=15, rotation=60)

ax.set_zlabel('$g_4$', fontsize=15, rotation=60)

plt.savefig('Constraints.jpg')

plt.show()

//img1.sycdn.imooc.com//61cc5242000185d505670501.jpg

查看完整回答
反对 回复 2021-12-29
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

这是对@Gio 的回答的更新。截至matplotlib 3.3.3,_facecolors3d并且_edgecolors3d不存在。所以,而不是这个:


c1._facecolors2d = c1._facecolors3d

c1._edgecolors2d = c1._edgecolors3d

这会导致类似的AttributeError,试试这个:


c1._facecolors2d = c1._facecolor3d

c1._edgecolors2d = c1._edgecolor3d

由于低代表,我不得不将其作为答案,而不是评论。


查看完整回答
反对 回复 2021-12-29
  • 2 回答
  • 0 关注
  • 471 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信