matplotlib 如何在中旋转xticklabels,使每个xticklabel之间的间距相等?[副本]

k2arahey  于 2023-06-23  发布在  其他
关注(0)|答案(3)|浏览(77)

此问题已在此处有答案

Aligning rotated xticklabels with their respective xticks(6个答案)
8个月前关闭。
如何在matplotlib中旋转xticklabels,使每个xticklabel之间的间距相等?
例如,使用以下代码:

import matplotlib.pyplot as plt
import numpy as np

# Data + parameters
fontsize = 20
t = np.arange(0.0, 6.0, 1)
xticklabels = ['Full', 'token emb', 'char emb', 'char LSTM', 
               'token LSTM', 'feed forward','ANN']

# Plotting
fig = plt.figure(1)
ax = fig.add_subplot(111)
plt.plot(t, t)
plt.xticks(range(0, len(t) + 1))
ax.tick_params(axis='both', which='major', labelsize=fontsize)
ax.set_xticklabels(xticklabels, rotation = 45)
fig.savefig('test_rotation.png', dpi=300, format='png', bbox_inches='tight')

本人获得:

每个xticklabel之间的间距不相等。例如,“Full”和“token emb”之间的间隔比“feed forward”和“ANN”之间的间隔大得多。
我在Windows 7 SP1 x64 Ultimate上使用Matplotlib 2.0.0和Python 3.5 64位。

7gs2gvoe

7gs2gvoe1#

标签在刻度线位置居中。它们的边界框宽度不等,甚至可能重叠,这使得它们看起来不相等。

由于您总是希望刻度标签链接到它们的刻度线,因此更改间距并不是一个真正的选择。
但是,您可能希望将它们对齐,以便右上角作为它们在刻度下方的位置参考。
使用horizontalalignmentha参数,并将其设置为"right"

ax.set_xticklabels(xticklabels, rotation = 45, ha="right")

这导致以下图:

另一种方法是保持ticklabel水平居中,但也可以垂直居中。这导致相等的间距,但需要进一步调整它们相对于轴线的垂直位置。

ax.set_xticklabels(xticklabels, rotation = 45, va="center", position=(0,-0.28))

如果像问题中那样手动指定刻度,则可以使用上述方法(例如通过plt.xticks或通过ax.set_xticks)或如果使用分类图。
如果自动显示标签,则不应使用set_xticklabels。这通常会使标签和刻度位置变得不同步,因为set_xticklabels将轴的格式化器设置为FixedFormatter,而定位器保持自动AutoLocator或任何其他自动定位器。
在这些情况下,可以使用plt.setp设置现有标注的旋转和对齐方式,

plt.setp(ax.get_xticklabels(), ha="right", rotation=45)

或在它们上循环以设置相应的属性,

for label in ax.get_xticklabels():
    label.set_ha("right")
    label.set_rotation(45)

举个例子

import numpy as np; np.random.seed(42)
import matplotlib.pyplot as plt

t = np.arange("2018-01-01", "2018-03-01", dtype="datetime64[D]")
x = np.cumsum(np.random.randn(len(t)))

fig, ax = plt.subplots()
ax.plot(t, x)

for label in ax.get_xticklabels():
    label.set_ha("right")
    label.set_rotation(45)

plt.tight_layout()
plt.show()
5rgfhyps

5rgfhyps2#

这里有一个很好的资源,提供了几个选项。他们并不完美,但基本上还行:
https://www.pythoncharts.com/2019/05/17/rotating-axis-labels/
更新:
我查看了matplotlib.text.Text.set_rotation_mode的文档(链接):

set_rotation_mode(self, m)

Set text rotation mode.

Parameters: 
m : {None, 'default', 'anchor'}
If None or "default", the text will be first rotated, 
then aligned according to their horizontal and vertical 
alignments. 
If "anchor", then alignment occurs before rotation.

因此,如果未指定rotation_mode,文本将首先旋转,然后对齐。在此模式下,即使使用ha="right",边界框也不完全位于文本的右上角。
如果为rotation_mode="anchor",则文本将直接绕锚点旋转(ha="right")。
下面是一个例子(改编自这里的代码)

import matplotlib
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1_bla_bla', 'G2_bla', 'G3_bla', 'G4_bla', 'G5_bla']
men_means = [20, 34, 30, 35, 27]
women_means = [25, 32, 34, 20, 25]
x = np.arange(len(labels))  # the label locations
width = 0.35  # the width of the bars
fig, ax = plt.subplots()
ax.bar(x - width/2, men_means, width, label='Men')
ax.bar(x + width/2, women_means, width, label='Women')
# Add some text for labels, title and custom x-axis tick labels, etc.
ax.set_ylabel('Scores')
ax.set_title('Scores by group and gender')
ax.set_xticks(x)
ax.set_xticklabels(
    labels, 
    rotation=30, 
    ha="right",  
    rotation_mode="anchor")  # <====== HERE is the key
ax.legend()
plt.show()

图现在具有正确的对齐方式:

kb5ga3dv

kb5ga3dv3#

如果旋转Angular 是~45度,那么Ernest的ha='right和gbinux的rotation_mode='anchor'是很棒的:

ax.set_xticklabels(xticklabels, rotation=45, ha='right', rotation_mode='anchor')

**然而,这对于其他旋转Angular 不起作用,**例如70度(见左侧子图)。

如果旋转Angular 不是~45度,则将ha='right'与**ScaledTranslation**组合(见右侧子图)。

按照how to move a tick's label中的说明应用**ScaledTranslation**:

...
ax.set_xticklabels(xticklabels, rotation=70, ha='right')

# create offset transform (x=5pt)
from matplotlib.transforms import ScaledTranslation
dx, dy = 5, 0
offset = ScaledTranslation(dx/fig.dpi, dy/fig.dpi, scale_trans=fig.dpi_scale_trans)

# apply offset transform to all xticklabels
for label in ax.xaxis.get_majorticklabels():
    label.set_transform(label.get_transform() + offset)

相关问题