简体   繁体   English

在matplotlib中给定位置上将3D条居中

[英]Center 3D bars on the given positions in matplotlib

Consider a 3D bar plot with custom grid lines: 考虑带有自定义网格线的3D条形图:

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.ticker import MultipleLocator
# This import registers the 3D projection, but is otherwise unused.
from mpl_toolkits.mplot3d import Axes3D  # noqa: F401 unused import

fig = plt.figure(figsize=(20, 10))
ax = fig.add_subplot(111, projection='3d')

ax.xaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_major_locator(MultipleLocator(1))
ax.zaxis.set_major_locator(MultipleLocator(2))

nx = 10
ny = 10

colors = cm.tab20(np.linspace(0, 1, nx))
width = depth = 0.1

for x in np.arange(nx):
    for y in np.arange(ny):
        ax.bar3d(x, y, 0, width, depth, x+y, shade=False, color = colors[x], edgecolor = 'black')

plt.show()

3D条形图示例

How can I place the bars so that the bars are centered where the grid lines cross each other in the xy plane? 如何放置横条,使横条在xy平面中的网格线相互交叉的位置居中?

I'm thinking about something like 我在想类似的东西

ax.bar3d(x+0.5*depth, y+0.5*width, ...)

only it is not clear to me what the offset is that matplotlib uses. 只是我不清楚matplotlib使用的偏移量是什么。 It should work for all depth and width values. 它应适用于所有depthwidth值。

For 2D bar plots there is an argument for this, align = 'center' , but it doesn't seem to work for 3D. 对于2D条形图,有一个参数align = 'center' ,但是它似乎不适用于3D。

What looks to you as a shift in coordinates is really just the projection in combination with the margins of the axes. 在您看来,坐标转换实际上只是投影与轴边距的组合。 Hence even if the bars are correctly positionned in their center they look offset and that offset is dependent on the axes size, viewing angle etc. 因此,即使这些条正确放置在其中心,它们的外观也会偏移,并且该偏移取决于轴的大小,视角等。

The solution to this is in principle given in this Q&A: Removing axes margins in 3D plot 此问题解答中原则上提供了解决方案: 删除3D图中的轴边距

You would center the bars by subtracting half of their width and add a patch to remove the margin of the zaxis. 您可以通过减去条形图宽度的一半来居中,并添加一个补丁以消除z轴的空白。 Then setting the lower z limit to 0 pins the bars to the grid and makes them look centered for any viewing angle. 然后将z的下限设置为0,将条形图钉固定到网格上,并使它们在任何视角下都居中。

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib.ticker import MultipleLocator
from mpl_toolkits.mplot3d import Axes3D 
from mpl_toolkits.mplot3d.axis3d import Axis

def _get_coord_info_new(self, renderer):
    mins, maxs, cs, deltas, tc, highs = self._get_coord_info_old(renderer)
    correction = deltas * [0,0,1.0/4]
    mins += correction
    maxs -= correction
    return mins, maxs, cs, deltas, tc, highs
if not hasattr(Axis, "_get_coord_info_old"):
    Axis._get_coord_info_old = Axis._get_coord_info  
Axis._get_coord_info = _get_coord_info_new


fig = plt.figure(figsize=(20, 10))
ax = fig.add_subplot(111, projection='3d')

ax.xaxis.set_major_locator(MultipleLocator(1))
ax.yaxis.set_major_locator(MultipleLocator(1))
ax.zaxis.set_major_locator(MultipleLocator(2))

nx = 10
ny = 10

colors = cm.tab20(np.linspace(0, 1, nx))
width = depth = 0.1

for x in np.arange(nx):
    for y in np.arange(ny):
        ax.bar3d(x-width/2., y-depth/2., 0, width, depth, x+y, shade=False, 
                 color = colors[x], edgecolor = 'black')

ax.set_zlim(0,None)

plt.show()

在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM