Matplotlib:调整刻度以适合图形

Matplotlib: Adjusting the ticks to fit within the figure

我有以下 matplotlib 代码,它所做的只是在 x 轴上绘制 0-20,在 y 轴上绘制 0-100

import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(20))
ax.set_yticks(range(100))
labels = ax.set_yticklabels(range(100))

我遇到的问题是并非所有标签实际上都适合 y 轴。

我想要做的是将最大标签大小除以图形的总面积来计算我可以放置多少个标签,这样我就可以将我的数据分组为 0-10、10-20、 30-40 并绘制它们而不是显示单独的标签 1,2,3,4,5,6,7,8...

我在查找标签的标签大小和图形的标签大小时遇到​​了问题(如果我错了请纠正我,也许它是以像素为单位的轴大小。这是我第一次使用 matplotlib)

如何找出 figure/axes 占用的像素数(宽度 + 高度)以及每个标签的像素数(宽度 + 高度)?

您可以使用 ax.get_position() 获取绘图中的轴范围,请参阅 axes 上的文档(我会 post 一个 link,但我目前的声誉确实如此不允许)。

tick labelsize 是在你的 matplotlibrc 文件中相对于你的字体大小定义的。查看一些细节 here。默认大小为 12pt,可以使用

更改
plt.rcParams['ytick.labelsize'] = small

来自标准的 matplotibrc 文件:

Special text sizes can be defined relative to font.size, using the following values: xx-small, x-small, small, medium, large, x-large, xx-large, larger, or smaller

解决您的问题的最简单方法可能是使用

更改总图形大小
fig = plt.figure(figsize=(10,30))

在您的案例中使用以下 result(请注意,该示例有点极端)。如果有太多的刻度标签,你不得不增加总的图形大小,你应该考虑像上面显示的那样减小刻度标签的大小或减少刻度标签的数量。

请注意,此过程涉及手动调整总绘图的大小 and/or 您的刻度标签,直到获得所需的输出。如果有更好的方法来做到这一点,我会很高兴看到它。

您可以使用 plt.savefig(output.png) 将绘图保存在当前工作目录中。如果你使用 plt.show() 并且图像大于弹出窗口-window,标签总是会被弄乱,因为总图缩小到 window 大小但标签大小保持不变。

希望这个回答对您有所帮助。

只需添加以下行:

plt.tight_layout()

另一种选择是将所有其他标签稍微向左推。除了较小的 yticklabel 尺寸外,这看起来还不错:

import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np

# Generate some random data
labels = 'abcdefghijklmnopqrstuvwxyz'
data = np.random.random((len(labels), 100))

# Plot it, setting the ticklabel size temporarily
# this is helpful for adjusting your plot until it's right
# without having an influence on other plots outside the context
with mpl.rc_context(rc={'ytick.labelsize': 6}):
    fig, ax = plt.subplots(1, 1, figsize=(6.5,5))
    im = ax.imshow(data)

    # Plot the labels on the yaxis
    ax.set_yticks(range(len(labels)))

    # Every second label gets a bit of whitespace to the right
    # thus effectively it is pushed to the left
    labels_formatted = [label if i%2==0 else label+' '*3 for i,label in enumerate(labels)]

    ax.set_yticklabels(labels_formatted)