【问题标题】:How to change spacing between ticks in matplotlib?如何更改 matplotlib 中刻度之间的间距?
【发布时间】:2017-12-05 09:53:40
【问题描述】:

我想使用以下代码在 X 轴上绘制一个带有很多刻度的图形:

import pylab

N = 100
data = pylab.np.linspace(0, N, N)

pylab.plot(data)

pylab.xticks(range(N)) # add loads of ticks
pylab.grid()
pylab.tight_layout()
pylab.show()

pylab.close()

生成的图如下所示:

如您所见,X 轴一团糟,因为刻度标签之间的间距太小甚至重叠

我想在每个刻度标签之间自动创建恒定的空间,无论有多少刻度。所以,我想增加单个刻度之间的空间,从而可能增加绘图的“长度”。

请注意,刻度标签可能是可变长度的字符串

到目前为止,我发现的都是关于spacing between the axis and labels(这不是我想要的)、tick frequency(我已经可以做到)和tick parameters(似乎没有任何间距选项)。

我可以使用matplotlib.pyplot.figure(figsize=(a, b)) 手动更改图形的大小,但这需要知道刻度之间的默认间距(据我所知没有)和刻度的最大宽度(英寸)标签,我不知道如何衡量,所以在我看来,这不是一个选择。

我可以做些什么来增加刻度之间的间距?我可以得到一个相当长的图像。

【问题讨论】:

  • 这就是 matplotlib 的工作方式。您创建一个给定大小的图形并将绘图放入其中。如果有更多标签,它们将重叠。您当然可以在创建后更改图形大小;找出最长标签占用的空间,将其乘以标签数量,添加边距并将其设置为新的图形大小。这是一个相当复杂的过程,所以我不确定这是否真的是您想要的。
  • @ImportanceOfBeingErnest,我在最后一段中谈到了这一点,这确实似乎很难做到,因为我不知道如何计算最长标签占用的空间......我希望有一些不错的技巧可以做到这一点。
  • 是的,这就是我的观点。很明显,您排除了唯一可能的解决方案。你想不想走那条路?我想您可以沿着这条线寻求帮助,而不是排除该选项。

标签: python matplotlib plot


【解决方案1】:

您可以使用以下方法来旋转标签并缩小字体:

ax.set_xticklabels(rotation = (45), fontsize = 10, va='bottom', ha='left')

【讨论】:

  • 问题是,我想故意绘制很多个刻度,不幸的是它们会重叠。
  • 如果你使用类似的东西:ax.set_xticklabels(rotation = (45), fontsize = 10, va='bottom', ha='left') 来旋转标签
  • @ser,您是否阅读了问题并访问了我放在那里的链接? 第一个是指向这个问题的链接,这是一个非常不同的问题。
  • @ChristianDean 我刚刚编辑了我的评论。我认为ax.set_xticklabels 应该可以解决问题
  • @ser,不,这不起作用,这是我已经尝试过的另一个 SO 答案的 sn-p。
【解决方案2】:

刻度标签之间的间距完全由轴上刻度之间的间距决定。因此,在给定刻度标签之间获得更多空间的唯一方法是使轴更大。

为了确定标签不重叠所需的空间,可以找出最大的标签并将其长度乘以刻度标签的数量。然后可以调整轴周围的边距并将计算的大小设置为新的图形大小。

import numpy as np
import matplotlib.pyplot as plt

N = 150
data = np.linspace(0, N, N)

plt.plot(data)

plt.xticks(range(N)) # add loads of ticks
plt.grid()

plt.gca().margins(x=0)
plt.gcf().canvas.draw()
tl = plt.gca().get_xticklabels()
maxsize = max([t.get_window_extent().width for t in tl])
m = 0.2 # inch margin
s = maxsize/plt.gcf().dpi*N+2*m
margin = m/plt.gcf().get_size_inches()[0]

plt.gcf().subplots_adjust(left=margin, right=1.-margin)
plt.gcf().set_size_inches(s, plt.gcf().get_size_inches()[1])

plt.savefig(__file__+".png")
plt.show()

请注意,如果绘图窗口中显示的图形大于屏幕,它将再次缩小,因此调整大小的图形仅在保存时以新大小显示。或者,可以选择将其合并到带有滚动条的某些窗口中,如以下问题所示:Scrollbar on Matplotlib showing page

【讨论】:

  • 哇,效果很好,谢谢!不过,我偶然发现了一个小问题:Y 轴的一些刻度标签得到cut off,大概是因为plt.gca().margins(x=0)。对此有什么办法吗?
  • margins(x=0) 是内边距,与外面的剪切标签无关。相反,在上面的代码中,我选择了m = 0.2 # inch margin,因此如果您想要在轴周围有更多空间,请使用更大的值m
  • 太棒了,现在一切都完美无缺!谢谢!
【解决方案3】:

这是一个老问题,但对于任何搜索的人来说,有一种方法:ticker.MaxNLocator(以及那里的其他定位器)。无论缩放大小如何,它都可以在图表上放置最多 N 个刻度。

【讨论】:

    【解决方案4】:

    另一种解决方案是调整数据以使刻度间距起作用。

    注意:如果您有大量数据,这可能会变得非常困难

    import matplotlib.pyplot as plt
    import numpy as np
    
    # **************************************************************************
    # This plot shows inconsistent spacing between ticks
    # **************************************************************************
    f, test = plt.subplots()
    xdata = [0,1,5,6,9,10]
    ydata = [1,2,3,4,5,6]
    test.step(xdata,ydata)
    test.set_xticks([0,1,5,6,9,10],['Zero', 'one', 'five', 'six', 'nine', 'ten'])
    
    plt.show()
    
    # **************************************************************************
    # Adjust data so tick marks have consistent spacing
    # **************************************************************************
    prettyxdata = xdata
    for i in range(len(xdata)):
        if prettyxdata [i] == 5:
            prettyxdata [i]=2
        elif prettyxdata [i] == 6:
            prettyxdata [i]=3
        elif prettyxdata [i] == 9:
            prettyxdata [i]=4
        elif prettyxdata [i] == 10:
            prettyxdata [i]=5
    
    f, test = plt.subplots()
    test.step(prettyxdata,ydata)
    test.set_xticks([0,1,2,3,4,5],['Zero', 'one', 'five', 'six', 'nine', 'ten'])
    
    plt.show()
    

    【讨论】: