繁体   English   中英

如何在matplotlib中移动刻度标签?

[英]How to move a tick's label in matplotlib?

我想沿 x 轴水平移动一些刻度的标签,而不移动相应的刻度。

更具体地说,当使用plt.setp旋转标签时,标签文本的中心与刻度保持对齐。 我想将这些标签向右移动,以便标签的近端对齐,而不是如下图所示。

在此处输入图片说明

我知道这篇文章这一个,但答案很有意思组装机,而不是严格的问题的答案。

我的代码:

import matplotlib.pyplot as plt
import numpy as np
import datetime

# my fake data
dates = np.array([datetime.datetime(2000,1,1) + datetime.timedelta(days=i) for i in range(365*5)])
data = np.sin(np.arange(365*5)/365.0*2*np.pi - 0.25*np.pi) + np.random.rand(365*5) /3

# creates fig with 2 subplots
fig = plt.figure(figsize=(10.0, 6.0))
ax = plt.subplot2grid((2,1), (0, 0))
ax2 = plt.subplot2grid((2,1), (1, 0))
## plot dates
ax2.plot_date( dates, data )

# rotates labels 
plt.setp( ax2.xaxis.get_majorticklabels(), rotation=-45 ) 

# try to shift labels to the right
ax2.xaxis.get_majorticklabels()[2].set_y(-.1)
ax2.xaxis.get_majorticklabels()[2].set_x(10**99)

plt.show()

奇怪的是, set_y行为符合预期,但即使我将x设置为 fantasillion,标签也不会移动一毫。 (使用plot_date可能会引入额外的混乱,但实际上同样发生在plot 。)

首先,让我们使用mcve来显示问题。

import numpy as np
import datetime
import matplotlib.pyplot as plt
plt.rcParams["date.autoformatter.month"] = "%b %Y"

# my fake data
dates = np.array([datetime.datetime(2000,1,1) + datetime.timedelta(days=i) for i in range(365)])
data = np.sin(np.arange(365)/365.0*2*np.pi - 0.25*np.pi) + np.random.rand(365) /3

# creates fig with 2 subplots
fig, ax = plt.subplots(figsize=(6,2))
## plot dates
ax.plot_date( dates, data )

# rotates labels 
plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45 ) 

plt.tight_layout()
plt.show()

在此处输入图片说明

现在正如其他答案已经指出的那样,您可以使用文本的水平对齐方式。

# rotates labels and aligns them horizontally to left 
plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45, ha="left" )

在此处输入图片说明

您可以使用rotation_mode参数让旋转发生在文本的左上角,在这种情况下会得到更好的结果。

# rotates labels and aligns them horizontally to left 
plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45, ha="left", rotation_mode="anchor") 

在此处输入图片说明

如果这些选项不够细粒度,即您想更准确地定位标签,例如将其移动到一边一些点,您可以使用变换。 以下将使用matplotlib.transforms.ScaledTranslation在水平方向上将标签偏移 5 个点。

import matplotlib.transforms

plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45) 

# Create offset transform by 5 points in x direction
dx = 5/72.; dy = 0/72. 
offset = matplotlib.transforms.ScaledTranslation(dx, dy, fig.dpi_scale_trans)

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

在此处输入图片说明

与例如@explorerDude 提供的解决方案相比,这样做的优点是偏移量与图中的数据无关,因此它通常适用于任何绘图,并且对于给定的字体大小看起来相同。

代替

ax2.xaxis.get_majorticklabels()[2].set_y(-.1)
ax2.xaxis.get_majorticklabels()[2].set_x(10**99)

set_horizontalalignment()的每个刻度使用set_horizontalalignment()

for tick in ax2.xaxis.get_majorticklabels():
    tick.set_horizontalalignment("left")

导致:

我找到了一种方法,可以任意精确地移动 x 轴的刻度标签,但这种方法非常接近高耸于疯狂之海之上的陡峭而滑溜的悬崖。 所以只有非常勇敢或绝望的人才应该继续阅读……

话虽如此,问题是在渲染绘图时设置了标签的 x 位置(我没有研究那部分代码,但这是我的理解)。 所以你用 set_x() 做的一切都会在以后被覆盖。 但是,有一种方法可以解决这个问题:您可以对某些刻度进行猴子补丁 set_x,这样标签就不会绘制在渲染器想要绘制它们的位置:

import types
SHIFT = 10. # Data coordinates
for label in ax2.xaxis.get_majorticklabels():
    label.customShiftValue = SHIFT
    label.set_x = types.MethodType( lambda self, x: matplotlib.text.Text.set_x(self, x-self.customShiftValue ), 
                                    label, matplotlib.text.Text )

您可以仅对要移动的标签有选择地执行此操作,当然您也可以为每个标签使用不同的移动。

如果有人知道如何在较低的疯狂水平上做到这一点,我会非常感兴趣......

另一种进行水平对齐的方法:

plt.xticks(ha='left')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM