如果高度为零,Matplotlib 在 bar3d 中隐藏栏

Posted

技术标签:

【中文标题】如果高度为零,Matplotlib 在 bar3d 中隐藏栏【英文标题】:Matplotlib hide bar in bar3d if height is zero 【发布时间】:2022-01-08 18:48:46 【问题描述】:

我见过matplotlib invisible bar if height is zero - 但是,这是针对二维条形图的情况,所以我无法将其完全应用于我的问题。

我还看到了Make transparent color bar with height 0 in matplotlib,它应该可用于 3D 案例 - 但是,我不想让零高度条透明,我想隐藏它们,以在交互(旋转)时加快渲染速度3D 绘图。

这是一个示例,基于Create 3D histogram of 2D data — Matplotlib 3.5.0 documentation:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
x = y = np.concatenate([np.array([5,4,3,2,1]), np.zeros(35)])
hist, xedges, yedges = np.histogram2d(x, y, bins=40, range=[[0, 40], [0, 40]])

# Construct arrays for the anchor positions of the 16 bars.
xpos, ypos = np.meshgrid(xedges[:-1] + 0.25, yedges[:-1] + 0.25, indexing="ij")
xpos = xpos.ravel()
ypos = ypos.ravel()
zpos = 0

# Construct arrays with the dimensions for the 16 bars.
dx = dy = 0.5 * np.ones_like(zpos)
dz = hist.ravel()

ax.bar3d(xpos, ypos, zpos, dx, dy, dz, zsort='average')

plt.show()

运行它会创建这个情节:

大多数条形图的高度为 0,但数量很多,因此旋转图有点慢。

我曾尝试像这样“屏蔽”,如Make transparent color bar with height 0 in matplotlib:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
x = y = np.concatenate([np.array([5,4,3,2,1]), np.zeros(35)])
hist, xedges, yedges = np.histogram2d(x, y, bins=40, range=[[0, 40], [0, 40]])

# Construct arrays for the anchor positions of the 16 bars.
xpos, ypos = np.meshgrid(xedges[:-1] + 0.25, yedges[:-1] + 0.25, indexing="ij")
xpos = xpos.ravel()
ypos = ypos.ravel()
zpos = 0

# Construct arrays with the dimensions for the 16 bars.
dx = dy = 0.5 * np.ones_like(zpos)
dz = hist.ravel()

mask_dz = dz == 0 # SO:60111736, 3d case

ax.bar3d(xpos[~mask_dz], ypos[~mask_dz], zpos[~mask_dz], dx[~mask_dz], dy[~mask_dz], dz[~mask_dz], zsort='average')

plt.show()

...但这失败了:

Traceback (most recent call last):
  File "D:\msys64\tmp\test.py", line 22, in <module>
    ax.bar3d(xpos[~mask_dz], ypos[~mask_dz], zpos[~mask_dz], dx[~mask_dz], dy[~mask_dz], dz[~mask_dz], zsort='average')
TypeError: 'int' object is not subscriptable

我怎样才能得到与前面所示相同的图 - 除了隐藏所有零高度条?

【问题讨论】:

【参考方案1】:

在写这个问题的时候,我偶然发现了正确的解决方案——基本上,并不是所有的 xpos,... dx,... 都是数组,所以我们不应该在它们不存在的地方应用掩码:

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.add_subplot(projection='3d')
x = y = np.concatenate([np.array([5,4,3,2,1]), np.zeros(35)])
hist, xedges, yedges = np.histogram2d(x, y, bins=40, range=[[0, 40], [0, 40]])

# Construct arrays for the anchor positions of the 16 bars.
xpos, ypos = np.meshgrid(xedges[:-1] + 0.25, yedges[:-1] + 0.25, indexing="ij")
xpos = xpos.ravel()
ypos = ypos.ravel()
zpos = 0

# Construct arrays with the dimensions for the 16 bars.
dx = dy = 0.5 * np.ones_like(zpos)
dz = hist.ravel()

mask_dz = dz == 0 # SO:60111736, 3d case

ax.bar3d(xpos[~mask_dz], ypos[~mask_dz], zpos, dx, dy, dz[~mask_dz], zsort='average')
# after the above command, the plot range xlim and ylim gets set to [0,6] - so re-set it back to same as on original image
ax.set_xlim([0, 40])
ax.set_ylim([0, 40])

plt.show()

...这个情节的结果:

...确实更容易与之交互。

请注意,应用蒙版后,绘图的 xlim 和 ylim 会重置为与 OP 中显示的范围不同的范围,因此需要重新应用范围,以获得与中相同的绘图范围可视化OP。

【讨论】:

以上是关于如果高度为零,Matplotlib 在 bar3d 中隐藏栏的主要内容,如果未能解决你的问题,请参考以下文章

$(document).ready() 内的 div 高度为零

如果当前部分单元格高度为零,则不会为后续部分调用索引路径处的行的 Collectionview 单元格

iOS - UIScrollView 内容大小设置为零

旋转iOS后子视图控制器高度为零

使自定义单元格(使用自动布局创建)高度为零

为啥标签的高度为零?