如何在 matplotlib 中移动刻度标签

Posted

技术标签:

【中文标题】如何在 matplotlib 中移动刻度标签【英文标题】:How to move a tick label in matplotlib 【发布时间】:2015-04-21 08:37:12 【问题描述】:

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

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

我知道this post 和this one,但是答案是有趣的组合,而不是对问题的严格回答。

我的代码:

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 也会发生同样的情况。)

【问题讨论】:

【参考方案1】:

代替

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

对轴上的每个刻度使用set_horizontalalignment()

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

导致:

【讨论】:

感谢您的回答。但是它并没有提供太多的灵活性:“左”、“右”、“中心”。我正在尝试分配确切的坐标。我花了很多时间尝试,我真正关心的是知道这是否可能。【参考方案2】:

我找到了一种方法,可以将 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 )

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

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

【讨论】:

如果你知道刻度位置,你可以做类似 pos, tick in zip(ticks, ax.xaxis.get_majorticklabels()): tick.set_x(pos - 0.1) tick.set_x = lambda x: 无 ...我不知道如何在评论中获取代码,但希望你能明白要点。【参考方案3】:

另一种水平对齐方式:

plt.xticks(ha='left')

【讨论】:

【参考方案4】:

首先,让我们使用 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 提供的解决方案是偏移量独立于图表中的数据,因此它通常适用于任何绘图并且对于给定的字体大小看起来相同。

【讨论】:

精彩的回答谢谢!为什么dx 有 72 作为分母?你是怎么得到这个号码的? Matplotlib 图形使用每英寸 72 点 (ppi)。因此,要将某物移动 x 点,您可以将其移动 x/72 英寸。您可能还想阅读 this answer 了解 dpi/ppi。 非常感谢您使用转换的最终答案,我陷入了疯狂的变通办法,但这很好用! 这个答案很好,尽管对我来说 xticklabels 的水平移位在将 plt.savefit 导出到 png(后端 Qt5Agg)的图像时会丢失。 如何将其应用于单个刻度标签? IE。向左移动一个标签?

以上是关于如何在 matplotlib 中移动刻度标签的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 matplotlib 中绘图的轴、刻度和标签的颜色

Matplotlib 使刻度标签字体变小

如何在 matplotlib 条形图上旋转 x 轴刻度标签?尝试了几种方法,都没有奏效

如何在 matplotlib 条形图上旋转 x 轴刻度标签?尝试了几种方法,都没有奏效

matplotlib 颜色条刻度标签格式

如何更改 matplotlib 图的日期时间刻度标签频率?