将旋转的 xticklabels 与其各自的 xtick 对齐
- 2025-01-13 08:53:00
- admin 原创
- 121
问题描述:
检查下图的 x 轴。如何将标签稍微向左移动,以便它们与各自的刻度对齐?
我使用以下方法旋转标签:
ax.set_xticks(xlabels_positions)
ax.set_xticklabels(xlabels, rotation=45)
但如您所见,旋转以文本标签的中间为中心。这使得它们看起来像是向右移动了。
我尝试过用这个来代替:
ax.set_xticklabels(xlabels, rotation=45, rotation_mode="anchor")
...但它并没有达到我的期望。而且"anchor"
似乎是该参数唯一允许的值rotation_mode
。
解决方案 1:
您可以设置刻度标签的水平对齐方式,请参见下面的示例。如果您想象一个围绕旋转标签的矩形框,您希望矩形的哪一侧与刻度点对齐?
根据您的描述,您想要:ha='right'
n=5
x = np.arange(n)
y = np.sin(np.linspace(-3,3,n))
xlabels = ['Ticklabel %i' % i for i in range(n)]
fig, axs = plt.subplots(1,3, figsize=(12,3))
ha = ['right', 'center', 'left']
for n, ax in enumerate(axs):
ax.plot(x,y, 'o-')
ax.set_title(ha[n])
ax.set_xticks(x)
ax.set_xticklabels(xlabels, rotation=40, ha=ha[n])
解决方案 2:
ha='right'
不足以在视觉上将标签与刻度对齐:
对于
rotation=45
,同时ha='right'
使用和rotation_mode='anchor'
对于其他角度,请
ScaledTranslation()
使用
rotation_mode='anchor'
如果旋转角度大约为 45°,则ha='right'
结合rotation_mode='anchor'
:
ax.set_xticks(ticks)
ax.set_xticklabels(labels, rotation=45, ha='right', rotation_mode='anchor')
或者在 matplotlib 3.5.0+ 中,一次设置刻度和标签:
ax.set_xticks(ticks, labels, rotation=45, ha='right', rotation_mode='anchor')
ScaledTranslation()
如果旋转角度更大(例如 70°)或者您只是想要更细粒度的控制,则锚定效果不佳。相反,应用线性变换:
ax.set_xticks(ticks)
ax.set_xticklabels(labels, rotation=70)
# create -5pt offset in x direction
from matplotlib.transforms import ScaledTranslation
dx, dy = -5, 0
offset = ScaledTranslation(dx / fig.dpi, dy / fig.dpi, fig.dpi_scale_trans)
# apply offset to all xticklabels
for label in ax.xaxis.get_majorticklabels():
label.set_transform(label.get_transform() + offset)
解决方案 3:
当然可以旋转标签。但请注意,这样做会降低文本的可读性。一种替代方法是使用如下代码来交替标签位置:
import numpy as np
n=5
x = np.arange(n)
y = np.sin(np.linspace(-3,3,n))
xlabels = ['Long ticklabel %i' % i for i in range(n)]
fig, ax = plt.subplots()
ax.plot(x,y, 'o-')
ax.set_xticks(x)
labels = ax.set_xticklabels(xlabels)
for i, label in enumerate(labels):
label.set_y(label.get_position()[1] - (i % 2) * 0.075)
有关更多背景信息和替代方案,请参阅我博客上的这篇文章
解决方案 4:
一种简单、无循环的替代方法是使用horizontalalignment
Text 属性作为 [1] 的关键字参数xticks
。在下面的注释行中,我强制将xticks
对齐设置为“右”。
n=5
x = np.arange(n)
y = np.sin(np.linspace(-3,3,n))
xlabels = ['Long ticklabel %i' % i for i in range(n)]
fig, ax = plt.subplots()
ax.plot(x,y, 'o-')
plt.xticks(
[0,1,2,3,4],
["this label extends way past the figure's left boundary",
"bad motorfinger", "green", "in the age of octopus diplomacy", "x"],
rotation=45,
horizontalalignment="right") # here
plt.show()
(yticks
默认情况下已经将右边缘与刻度对齐,但xticks
默认值似乎是“中心”。)
[1]如果您搜索短语“文本属性”,您会在xticks 文档中找到相关描述。
解决方案 5:
我显然迟到了,但有一个官方的例子使用
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", rotation_mode="anchor")
旋转标签,同时保持它们与刻度正确对齐,既干净又简单。
参见:https ://matplotlib.org/stable/gallery/images_contours_and_fields/image_annotated_heatmap.html
解决方案 6:
@tdy 的回答近乎完美。我认为让标签看起来漂亮的更快方法是结合使用以下所有三种设置:
ha='right'
va='top'
rotation_mode='anchor'
这样,就无需使用ScaledTranslation
。这似乎适用于所有旋转角度。
ax.set_xticklabels(labels, rotation=30, ha='right', va='top', rotation_mode='anchor')
``