Matplotlib subplots_adjust hspace以避免标题和x轴标签重叠?
在使用matplotlib绘制3行子图的时候,某一行的横坐标标签可能会和下一行的标题重叠。这时候就需要调整一下pl.subplots_adjust(hspace)
,这真的很麻烦。
有没有什么方法可以设置hspace
,让它避免重叠,并且适用于任意行数呢?
""" matplotlib xlabels overlap titles ? """
import sys
import numpy as np
import pylab as pl
nrow = 3
hspace = .4 # of plot height, titles and xlabels both fall within this ??
exec "\n".join( sys.argv[1:] ) # nrow= ...
y = np.arange(10)
pl.subplots_adjust( hspace=hspace )
for jrow in range( 1, nrow+1 ):
pl.subplot( nrow, 1, jrow )
pl.plot( y**jrow )
pl.title( 5 * ("title %d " % jrow) )
pl.xlabel( 5 * ("xlabel %d " % jrow) )
pl.show()
我的版本信息:
- matplotlib 0.99.1.1,
- Python 2.6.4,
- Mac OSX 10.4.11,
- 后端:
Qt4Agg
(TkAgg
会在Tkinter回调中出错)
(如果能多给点分数的话,有人能简单介绍一下matplotlib的打包器/间隔器是怎么工作的吗?可以参考Tcl/Tk书中的第17章“打包器”)
2 个回答
46
Jose发的链接已经更新,现在pylab里有一个叫做tight_layout()
的功能,可以自动处理这个问题(在matplotlib 1.1.0版本中)。
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.tight_layout
http://matplotlib.org/users/tight_layout_guide.html#plotting-guide-tight-layout
31
我觉得这个问题有点棘手,但在MatPlotLib的常见问题解答上有一些信息可以参考。这个过程比较麻烦,需要了解每个元素(比如刻度标签)占用的空间...
更新:
页面上提到,使用tight_layout()
这个函数是最简单的方法,它会自动调整间距。
如果不使用这个函数,页面还提供了一些方法来获取各种元素(例如标签)的大小,这样你就可以手动调整坐标轴元素的间距和位置。下面是来自上述常见问题解答的一个例子,它计算了一个非常宽的y轴标签的宽度,并相应地调整了坐标轴的宽度:
import matplotlib.pyplot as plt
import matplotlib.transforms as mtransforms
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(range(10))
ax.set_yticks((2,5,7))
labels = ax.set_yticklabels(('really, really, really', 'long', 'labels'))
def on_draw(event):
bboxes = []
for label in labels:
bbox = label.get_window_extent()
# the figure transform goes from relative coords->pixels and we
# want the inverse of that
bboxi = bbox.inverse_transformed(fig.transFigure)
bboxes.append(bboxi)
# this is the bbox that bounds all the bboxes, again in relative
# figure coords
bbox = mtransforms.Bbox.union(bboxes)
if fig.subplotpars.left < bbox.width:
# we need to move it over
fig.subplots_adjust(left=1.1*bbox.width) # pad a little
fig.canvas.draw()
return False
fig.canvas.mpl_connect('draw_event', on_draw)
plt.show()