Python 如何移动勾号';matplotlib中的标签?

Python 如何移动勾号';matplotlib中的标签?,python,matplotlib,label,Python,Matplotlib,Label,我想沿x轴水平移动一些记号的标签,而不移动相应的记号 更具体地说,当使用plt.setp旋转标签时,标签文本的中心与刻度保持对齐。我想将这些标签向右移动,以便标签的近端对齐,而不是如下图所示 我知道,但答案是 对这个问题的回答很有趣,而不是很严格 我的代码: import matplotlib.pyplot as plt import numpy as np import datetime # my fake data dates = np.array([datetime.datetime(

我想沿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
设置为一个幻想,标签也不会移动一点。 (使用
plot\u date
可能会带来额外的混淆,但在
plot
中也会出现同样的情况)

而不是

ax2.xaxis.get_majorticklabels()[2].set_y(-.1)
ax2.xaxis.get_majorticklabels()[2].set_x(10**99)
对轴上的每个记号使用以下选项:

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


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

也就是说,问题是在渲染图形时设置了标签的x位置(我没有查看代码的这一部分,但这是我的理解)。因此,您对set_x()所做的一切稍后都会被覆盖。但是,有一种方法可以解决此问题:您可以为某些记号使用monkey patch 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')

首先,让我们使用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()

现在,正如其他Anwer已经指出的,您可以使用文本的水平对齐

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

您可以使用
rotation\u 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提供的解决方案相比,这种方法的优点是偏移量独立于图形中的数据,因此它通常适用于任何绘图,并且对于给定的字体大小看起来都是一样的。

我无法用上面的代码复制您的图像…@MattDMo我试图复制它并运行它,我得到了正确的情节。但它有两个子地块。你有什么收获吗?谢谢你的回答。但它并没有提供太多的灵活性:“左”、“右”、“中”。我正试图分配精确的坐标。我花了很多时间尝试,所以我真正关心的是知道这是否可能。如果你知道记号的位置,你可以做一些类似于pos的事情,在zip中记号(记号,ax.xaxis.get_majorticklabels()):tick.set_x(pos-0.1)tick.set_x=lambda x:None。。。我不知道如何在评论中获取代码,但希望您能理解要点。回答得很好,谢谢!为什么
dx
的分母是72?你是怎么得到这个数字的?Matplotlib数字使用每英寸72点(ppi)。所以要移动x点,你可以移动x/72英寸。您可能还想阅读dpi/ppi。非常感谢您使用转换的最终答案,我正在进入疯狂的解决方案,但这非常有效!这个答案很好,但对我来说,当使用plt.savefit将图像导出到png(后端Qt5Agg)时,Xticklabel的水平移动会丢失。如何将其应用到单个刻度标签?例如,将单个标签向左移动?