如何在 matplotlib 中移动刻度标签
How to move a tick label in matplotlib
我想沿 x 轴水平移动一些刻度的标签,而不移动相应的刻度。
更具体地说,当使用 plt.setp
旋转标签时,标签文本的中心与刻度保持对齐。我想将这些标签向右移动,以便标签的近端对齐而不是如下图所示。
我知道 this post and 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
也会发生同样的情况。)
而不是
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")
导致:
我找到了一种将 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')
首先,让我们用一个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 提供的解决方案是偏移量独立于图中的数据,因此它通常适用于任何绘图并且对于给定的字体大小看起来相同。
我想沿 x 轴水平移动一些刻度的标签,而不移动相应的刻度。
更具体地说,当使用 plt.setp
旋转标签时,标签文本的中心与刻度保持对齐。我想将这些标签向右移动,以便标签的近端对齐而不是如下图所示。
我知道 this post and 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
也会发生同样的情况。)
而不是
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")
导致:
我找到了一种将 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')
首先,让我们用一个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
.
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 提供的解决方案是偏移量独立于图中的数据,因此它通常适用于任何绘图并且对于给定的字体大小看起来相同。