Python,Matplotlib:任意数量垂直图形的suptitle

3

我有一个网站,根据可用的数据站点运行情况,会产生任意数量的图表(作为图像),这些图表垂直堆叠在一起。以下是一个示例:

enter image description here

问题在于,根据垂直图的数量,suptitle(顶部标题)会位于不同的位置。请查看以下5个和10个绘图示例:
5个绘图:

enter image description here

这里有10个图表:

enter image description here

对于每个图形数量,我得到不同的结果。使用fig.tight_layout()没有帮助。
我需要的是让我的文本底部与图形顶部相隔一定距离。这个问题有一个通用的解决方案吗?
我创建了一些最小化的工作代码,其中包含参数化的图形数量。如果您想要重现这个问题,请查看它。
import datetime
import random
import matplotlib
matplotlib.use('Agg') # Force matplotlib not to use any Xwindows backend.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import matplotlib.image as mpimg
import matplotlib.gridspec as gridspec
import numpy as np


random.seed(datetime.datetime.now())

#initial parameters
numOfPlots  = 2
dataLen     = 100
randomRange = 10*dataLen
dpiVal      = 180

#create data
xData = list(range(dataLen) for x in range(numOfPlots))
yData = list(random.sample(range(randomRange), dataLen) for x in range(numOfPlots))

#matplotlib initialize plot
gs = gridspec.GridSpec(numOfPlots,1)
plt.cla()
plt.clf()
fig = plt.figure()
ax = None

for i in list(range(numOfPlots)):
    if i == 0:
        ax = fig.add_subplot(gs[i])
    else:
        ax = fig.add_subplot(gs[i],sharex=ax)

    ax.plot(xData[i], yData[i])

    labelSize = 10
    ax.set_ylabel("Hi there",size=8)
    ax.get_yaxis().set_label_coords(-0.07,0.5)
    plt.yticks(size=8)
    plt.ticklabel_format(style='sci', axis='y', scilimits=(0,0),useOffset=True)
    plt.subplots_adjust(hspace = 0.3)
    if i == numOfPlots-1:
        plt.xticks(rotation=0,size=7)
        max_xticks = 10
        xloc = plt.MaxNLocator(max_xticks)
        ax.xaxis.set_major_locator(xloc)
        ax=plt.gca()
    else:
        plt.tick_params(
        axis='x',          # changes apply to the x-axis
        labelbottom='off') # labels along the bottom edge are off
    ax_right = ax.twinx()
    ax_right.yaxis.set_ticks_position('right')
    ax_right.set_ylabel("Nice to see you!",size=labelSize)
    ax_right.get_yaxis().set_ticks([])


#the following sets the size and the aspect ratio of the plot
fig.set_size_inches(10, 1.8*numOfPlots)

fig.suptitle("Hi there, this is the first line\nAnd this is the second!!!")
fig.savefig("img_"+str(numOfPlots)+".png",bbox_inches='tight',dpi=dpiVal)

这些便利函数在需要一致输出时通常是无用的。也许你可以尝试手动操作 - Andras Deak -- Слава Україні
@AndrasDeak 很抱歉我不明白什么是手动的。您能否再详细解释一下? - The Quantum Physicist
请查看链接,它演示了如何使用特定于轴的位置添加文本注释。我尝试建议您尝试在最顶部的轴上执行此操作,以获得一些一致性。抱歉没有表达清楚 :) - Andras Deak -- Слава Україні
是的,但您不能使用文本手动编写字幕吗?将其相对于顶部轴定位,确保它始终放置在同一位置? - Andras Deak -- Слава Україні
@AndrasDeak 我不知道如何做到这一点,尤其是因为位置是图形数量的函数。我试图为它创建线性插值/外推,但那也行不通。甚至它都不是线性的!! - The Quantum Physicist
显示剩余2条评论
1个回答

0

我建议尝试手动添加文本注释,并使用图形相对坐标单位来确定位置。

考虑以下两个示例:

hf,ax = plt.subplots(nrows=3)
hf.text(0.5,0.92,
        "Hi there, this is the first line\nAnd this is the second!!!",
        horizontalalignment='center')
hf,ax = plt.subplots(nrows=7)
hf.text(0.5,0.92,
        "Hi there, this is the first line\nAnd this is the second!!!",
        horizontalalignment='center')

结果中的“suptitle”位于完全相同的位置:

case1 case2


这看起来还不错!然而,有一个问题。我进行了一些测试,发现垂直高度仍然是图形数量的函数(虽然比以前好了一些)...除了第二个参数之外,我还能用什么来修复它? - The Quantum Physicist
@TheQuantumPhysicist 我不确定我理解了。如果您打开我链接的两个图像,并在浏览器或图像查看器中切换它们,您会发现标题的位置完全相同。您是否修改了有关图形的某些内容?对于此操作,您应省略 tight_layout();该函数会对绘图进行动态修改,这将取决于子图的数量。 - Andras Deak -- Слава Україні
@TheQuantumPhysicist,我看了你的示例代码,但是没有看到tight_layout。我怀疑手动调整图形大小会影响位置。如果你的图形变得更长,它的相对于顶部轴的0.92纵坐标将会发生偏移。 - Andras Deak -- Слава Україні
2
这正是suptitle所做的(除了在0.98而不是0.92)。 - tacaswell
1
请参见http://matplotlib.org/devdocs/users/annotations_guide.html,了解更多可将文本放置在所需位置的强大工具(例如,在图形顶部边缘以下15像素处)。 - tacaswell
显示剩余2条评论

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