如何堆叠3D条形图

6
基本上是这个的3D版本:使用Matplotlib同时绘制两个直方图 不过我不知道如何在使用3D坐标轴时实现。
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np

kets = ["|00>","|01>","|10>","|11>"] #my axis labels

fig = plt.figure()
ax1  = fig.add_subplot(111,projection = '3d')

xpos = [0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3]
xpos = [i+0.25 for i in xpos]
ypos = [0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3]
ypos = [i+0.25 for i in ypos]
zpos = [0]*16

dx    = 0.5*np.ones(16)
dy    = 0.5*np.ones(16)
dz    = [1,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0]
dz2   = [0.2*i for i in dz] # to superimpose dz

ticksx = np.arange(0.5,4,1)
ticksy = np.arange(0.6,4,1)

ax1.bar3d(xpos, ypos, zpos, dx , dy ,dz,  color = '#ff0080', alpha = 0.5)

ax1.w_xaxis.set_ticklabels(kets)
ax1.w_yaxis.set_ticklabels(kets)
ax1.set_zlabel('Coefficient')

plt.xticks(ticksx,kets)
plt.yticks(ticksy,kets)

plt.show()
1个回答

5

你已经解决了问题的一半,因为第一个棘手的部分是将你的条形图设置为半透明,使用alpha=0.5。然而,还有一个更微妙的问题需要处理。

第一个天真的尝试是将你对bar3d的调用复制到另一个数据集中。这样做应该可以,而且在某种程度上确实可以。你的条形图完全重叠在一起(在dz2中,非零元素都包含在dz中较高的条形图中),所以我建议将较小的条形图变得不那么透明,将较高的条形图变得更加透明,像这样:

# less transparent
ax1.bar3d(xpos, ypos, zpos, dx , dy ,dz,  color = '#ff0080', alpha = 0.3)
# use dz2, fully opaque, and bluish
ax1.bar3d(xpos, ypos, zpos, dx , dy ,dz2,  color = '#008080', alpha = 1)

然而,这会产生丑陋和不需要的结果,即一些在z==0处的面貌似乎被渲染在z>0处的面前。这可能是特定于所使用的后端:我正在从ipython中运行它,并使用Qt4Agg后端。这也允许我围绕图形旋转,在这种情况下,显然存在着致命的渲染问题。这是一个静态图像:

image with rendering problem

在左边第二条栏中,您可以看到一级补丁该栏后面似乎在该栏的顶部补丁的前面。显然这不是您(或任何人)需要的。

经过一些尝试(以及this answer的有用提示),我意识到当同时绘制多个柱子时,bar3d会出现一些问题。解决方法很简单:使用循环逐个创建每个柱子,这个问题(几乎完全)就会消失:

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

kets = ["|00>","|01>","|10>","|11>"] #my axis labels

fig = plt.figure()
ax1  = fig.add_subplot(111,projection = '3d')

xpos = [0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3]
xpos = [i+0.25 for i in xpos]
ypos = [0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3]
ypos = [i+0.25 for i in ypos]
zpos = [0]*16

dx    = 0.5*np.ones(16)
dy    = 0.5*np.ones(16)
dz    = [1,0,0,0,0,1,0,0,0,0,0,1,0,0,1,0]
dz2   = [0.2*i for i in dz] # to superimpose dz

ticksx = np.arange(0.5,4,1)
ticksy = np.arange(0.6,4,1)

# only change here:
# new loop, changed alphas and a color
for k in range(len(xpos)):
    ax1.bar3d(xpos[k], ypos[k], zpos[k], dx[k] , dy[k] ,dz[k],  color = '#ff0080', alpha = 0.3)
    ax1.bar3d(xpos[k], ypos[k], zpos[k], dx[k] , dy[k] ,dz2[k],  color = '#008080', alpha = 1)


ax1.xaxis.set_ticklabels(kets)
ax1.yaxis.set_ticklabels(kets)
ax1.set_zlabel('Coefficient')

plt.xticks(ticksx,kets)
plt.yticks(ticksy,kets)

plt.show()

当使用交互式后端旋转此图时,很明显它的表现几乎完美(尽管从某些视角仍然存在轻微的故障)。这是来自固定解决方案的静态图像:

fixed barplot

最后,需要注意的是,即使没有渲染故障,理解这种重叠的条形图也并不容易。你在问题中提到的二维情况可以通过,因为两个峰很明显分开了。如果它们有巨大的重叠,那么这个图就会更难理解。我建议考虑其他的可视化方式,例如将每个条形分成两部分(每部分用一个垂直平面),并在每个位置侧面并排绘制两组z数据。


1
我尝试过了,看起来甚至更糟。肯定存在某种错误,因为深度感知变得奇怪了。 - M.V.
一个轻微的改进是不显示dz为零的条形图。这对我正在制作的8x8图表有很大帮助。 - M.V.
@M.Vasalakis 啊,谢谢。我能看出这两组条的选择规则是相同的,但我不知道背景。所以你的意思是重叠的两个条是一种颜色,而其余的(零列)是另一种颜色?还是你指的是完全不同的(也许是二维)表示形式? - Andras Deak -- Слава Україні
1
所有期望值都是白色带黑色轮廓的,每一行填充不同颜色。 - M.V.
@M.Vasalakis 啊,我想我明白了,谢谢 :) 很高兴听到你找到了更清晰的表达方式,也感谢你回复我! - Andras Deak -- Слава Україні
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接