Matplotlib:在子图之间居中刻度标签

3

默认情况下,刻度标签与它们所属的子图轴对齐。 是否可能将标签对齐,使其在两个子图之间居中?

import numpy as np
import matplotlib.pyplot as plt

data = [7, 2, 3, 0]
diff = [d - data[0] for d in data]
y = np.arange(len(data))

ax1 = plt.subplot(1, 2, 1)
ax1.barh(y, diff)
ax1.set_yticks(y + 0.4)
ax1.yaxis.set_major_formatter(matplotlib.ticker.NullFormatter())

ax2 = plt.subplot(1, 2, 2)
ax2.barh(y, data)
ax2.set_yticks(y + 0.4)
ax2.set_yticklabels(['reference', 'something', 'something else', 'nothing', ])

plt.tight_layout()
plt.show()

labels aligned to the right subplot

1个回答

5
这是一种可行但不太方便的方法。当设置xticklabels时,您可以提供一个position关键字。这允许您在轴坐标中使用负偏移量。如果手动设置轴的位置和它们之间的间距,您可以计算出标签需要的负偏移量,使其恰好位于两个轴之间的中心位置。
给定您的示例数据:
fig = plt.figure(figsize=(10, 2), facecolor='w')
fig.subplots_adjust(wspace=0.2)

ax1 = fig.add_axes([0.0, 0, 0.4, 1])
ax2 = fig.add_axes([0.6, 0, 0.4, 1])

ax1.barh(y, diff, align='center')
ax1.set_yticks(y)
ax1.yaxis.set_major_formatter(matplotlib.ticker.NullFormatter())

ax2.barh(y, data, align='center')
ax2.set_yticks(y)
ax2.set_yticklabels(['reference', 'something', 'something else', 'nothing', ], 
                    ha='center', position=(-0.25, 0))

enter image description here

在图形坐标中,两个轴的宽度都为0.4,并且它们之间的间距为0.2。这意味着标签必须位于图形坐标的0.5处。由于第二个轴从0.6开始,因此它需要在图形坐标中偏移-0.1。不幸的是,位置应该以轴坐标给出。轴宽度为0.4,因此轴宽度的四分之一在图形坐标中为0.1。这意味着指定负四分之一的偏移量(-0.25)将标签放置在两个轴之间。希望这样解释清楚了。

请注意,我使用ha ='center'yticklabels居中。并且居中了您的条形图,因此在设置ticks时无需再指定偏移量。

编辑:

您可以通过读取两个轴的位置来自动执行此操作。

def center_ylabels(ax1, ax2):

    pos2 = ax2.get_position()
    right = pos2.bounds[0]    

    pos1 = ax1.get_position()
    left = pos1.bounds[0] + pos1.bounds[2]

    offset = ((right - left) / pos2.bounds[2]) * -0.5

    for yt in ax2.get_yticklabels():        
        yt.set_position((offset, yt.get_position()[1]))
        yt.set_ha('center')

        plt.setp(ax2.yaxis.get_major_ticks(), pad=0)

fig, (ax1, ax2) = plt.subplots(1,2, figsize=(10,2))
fig.subplots_adjust(wspace=0.5)

ax1.barh(y, diff, align='center')
ax1.set_yticks(y)
ax1.yaxis.set_major_formatter(matplotlib.ticker.NullFormatter())

ax2.barh(y, data, align='center')
ax2.set_yticks(y)
ax2.set_yticklabels(['reference', 'something', 'something else', 'nothing'])

center_ylabels(ax1, ax2)

enter image description here


好的建议,谢谢。请原谅我暂时还没有接受你的答案,但我仍然希望有人能提出一个自动化的解决方案... - undefined
你也可以使用这种技术来自动完成。我已经编辑了我的回答。 - undefined
需要手动调整子图之间的间距,对吗? - undefined
不,这不是为了居中y轴标签。你也可以在你的示例中使用它,只要在调用tight_layout之后放置函数center_ylabels(ax1, ax2),因为该函数会干扰轴的位置。 - undefined
没错,那可以运行。有没有想法为什么标签不是完全居中,而是稍微向左偏移了一点? - undefined
仍然应用了填充,我已经更新了函数,并将填充设置为0。 - undefined

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