Matplotlib 3D图形的刻度标签位置

12

我正在尝试解决如何设置/更正3D matplotlib图中刻度标签的位置。刻度标签与刻度不对齐。当需要许多刻度标签时,问题似乎特别突出。

我修改了matplotlib文档中的示例(http://matplotlib.org/examples/mplot3d/polys3d_demo.html)以说明我的问题。

from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PolyCollection
from matplotlib.colors import colorConverter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure(figsize=(10,10))
ax = fig.gca(projection='3d')

cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6)

xs = np.arange(0, 10, 0.4)
verts = []
zs = np.arange(50)
for z in zs:
    ys = np.ones(len(xs))*z
    ys[0], ys[-1] = 0, 0
    verts.append(list(zip(xs, ys)))

poly = PolyCollection(verts,facecolor='c')
poly.set_alpha(0.7)
ax.add_collection3d(poly, zs=zs, zdir='y')

ax.set_xlabel('X')
ax.set_xlim3d(0, 10)
ax.set_ylabel('Y')
ax.set_ylim3d(-1, len(zs))
ax.set_yticks(np.arange(len(zs)))
labels = {}
for l_c in zs:
    labels[l_c] = 'This Looks Bad'
ax.set_yticklabels(labels,rotation=-15)
ax.set_zlabel('Z')
ax.set_zlim3d(0, ys.max())

plt.show()

enter image description here

所以问题是:如何使刻度标签与刻度位置对齐?

3个回答

17
通过使用这些对齐方式,我可以获得更好的布局:
ax.set_yticklabels(labels,rotation=-15,
                   verticalalignment='baseline',
                   horizontalalignment='left')

我已经修改了例子,减少了刻度标记,以便您可以看到它们的位置:

输入图片描述


@random.me 你需要“_ticks_”还是“_text_”? - tacaswell
@tcaswell 我需要刻度标签。它们将是文本。 - random.me
@Hooked 是的,字体大小可以缩小,在我的问题中,图形可能相当大,而字体大小相当小,因此空间问题不太麻烦。 - random.me
@random.me 由于您最初发布的代码存在语法错误(请参见编辑),因此我缩小了图形大小,以便截图不会太大。另外,您真的应该为有帮助的答案点赞并选择正确的答案。关于对齐的原始问题已经得到解答,可能很好地提出一个新问题,探讨在绘图中塞入许多标签的技巧。 - Hooked
@Hooked 关于编辑:对我来说,figure(figsize=(10,10))figure(figsize(10,10))都可以工作。后者是语法错误吗?关于你的旁白:两个答案都很有帮助(已经点赞),但我不认为原始问题得到解决。当我恢复到figsize=(20,20)时,两个解决方案都没有产生正确/期望的对齐方式。我很乐意接受一个能够实现所需对齐的答案。也许我应该将原始问题中的代码返回到figure(figsize=(20,20)),以便问题可观察 - 你觉得呢? - random.me
显示剩余2条评论

6

它们确实对齐了,但水平位置是以刻度线居中为基准的。因为是在 3D 视图下,所以他们看起来比你预期的位置略低一些。这个效果与刻度线数量无关,而是与宽度有关。

特别设置对齐方式会有所帮助。尝试添加以下内容:

ax.set_yticklabels(labels,rotation=-15, va='center', ha='left')

试着玩一下不同的对齐方式,看看哪种更适合你,我认为你想要 ha='left'。

减少填充,与刻度线的距离也可能有所帮助。

输入图像描述


2
作为对楼主的说明:va在我的示例中与verticalalignment是同义词。同样,hahorizontalalignment也是如此。 - Hooked
是的,谢谢你澄清这一点,缩写在频繁输入时确实很方便。 :) - Rutger Kassies
谢谢@Rutger。我想这是最好的解决方案了。我已经尝试过这些(ha,va)并且几乎得到了我想要的结果。它在这个玩具示例上的效果比我正在尝试解决的实际问题要好。您能否举个例子来减少填充?也许可以在您现有的答案中添加。 - random.me
我在考虑像 ax.tick_params(axis='y', pad=30) 这样的东西,但事实证明这只适用于二维图。您能否澄清一下您在回应 Hooked 时提到的“错位”是什么意思。我认为它们完全对齐了。想象一下旋转标签周围的矩形框,并想象每个角上有一个点以及这些点之间的四个点。问题是这8个点中的哪一个要放置在刻度标签所在的位置(该位置与实际刻度相距一定距离)。 - Rutger Kassies
@RutgerKassies 是的,我也尝试过类似的方法,但没有成功。实际上,原始帖子已经被编辑成更小的图像 - 最初是 figsize=(20,20)。在这个比例下,与两个当前答案的错位仍然存在。回答你的问题:我想要通过想象的矩形框中心的线,沿着水平轴通过,与刻度标记对齐。我希望标签和刻度之间的间隙更小,最好可控。 - random.me
如果您不想被要求提供固定的标签文本,可以尝试以下方法:plt.setp(ax.get_yticklabels(), verticalalignment='baseline', horizontalalignment='left') - NicoH

2
您可以在每个轴的tick_params选项中将pad参数设置为负值。像这样:
    ax.tick_params(axis='x', which='major', pad=-3)

这可能有助于调整刻度标签与轴之间的距离。

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