Python 如何在matplotlib中移动刻度标签?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28615887/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to move a tick's label in matplotlib?
提问by snake_charmer
I would like to move some ticks' labels horizontally along the x-axis, without moving the corresponding ticks.
我想沿 x 轴水平移动一些刻度的标签,而不移动相应的刻度。
More specifically, when rotating labels with plt.setp
, the centers of the labels' text stay aligned with the ticks. I would like to shift those labels to the right, so that the near ends of the labels get aligned instead as suggested on the image below.
更具体地说,当使用 旋转标签时plt.setp
,标签文本的中心与刻度保持对齐。我想将这些标签向右移动,以便标签的近端对齐,而不是如下图所示。
I am aware of this postand this one, however the answers are interesting kludges rather than strict answers to the question.
我知道这篇文章和这一个,但答案很有意思组装机,而不是严格的问题的答案。
my code:
我的代码:
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()
Strangely enough, set_y
behaves as expected, but even if I set x
to a fantasillion, the labels would not move by one iota.
(The use of plot_date
may introduce additional confusion, but the same actually happens with plot
.)
奇怪的是,set_y
行为符合预期,但即使我设置x
为 fantasillion,标签也不会移动一毫。(使用plot_date
可能会带来额外的混乱,但实际上同样会发生在plot
.)
采纳答案by ImportanceOfBeingErnest
First of all, let's use a mcve to show the problem.
首先,让我们使用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()
Now as other anwers pointed out already, you may use horizontal alignment of the text.
现在正如其他答案已经指出的那样,您可以使用文本的水平对齐方式。
# rotates labels and aligns them horizontally to left
plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45, ha="left" )
You may use the rotation_mode
argument to let the rotation happen about the top left point of the text, giving a slightly nicer result in this case.
您可以使用rotation_mode
参数让旋转发生在文本的左上角,在这种情况下会得到更好的结果。
# rotates labels and aligns them horizontally to left
plt.setp( ax.xaxis.get_majorticklabels(), rotation=-45, ha="left", rotation_mode="anchor")
In case those options are not fine grained enough, i.e. you want to position the labels more accurately, e.g. shifting it to the side by some points, you may use a transform. The following would offset the label by 5 points in horizontal direction, using a matplotlib.transforms.ScaledTranslation
.
如果这些选项不够细粒度,即您想更准确地定位标签,例如将其移动到一边一些点,您可以使用变换。以下将使用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)
The advantage of this, compared to e.g. the solution provided by @explorerDude is that the offset is independent on the data in the graph, such that it is generally applicable to any plot and would look the same for a given fontsize.
与例如@explorerDude 提供的解决方案相比,这样做的优点是偏移量与图中的数据无关,因此它通常适用于任何绘图并且对于给定的字体大小看起来相同。
回答by MattDMo
Instead of
代替
ax2.xaxis.get_majorticklabels()[2].set_y(-.1)
ax2.xaxis.get_majorticklabels()[2].set_x(10**99)
use the set_horizontalalignment()
for each tick on the axis:
set_horizontalalignment()
对轴上的每个刻度使用:
for tick in ax2.xaxis.get_majorticklabels():
tick.set_horizontalalignment("left")
resulting in:
导致:
回答by explorerDude
I found a way to shift the tick labels of the x-axis by an arbitrary and exact amount, but this way runs dangerously close to the steep and slippery cliffs towering above the sea of madness. So only the very brave or desperate should read on...
我找到了一种方法,可以任意精确地移动 x 轴的刻度标签,但这种方法非常接近高耸于疯狂之海之上的陡峭而滑溜的悬崖。所以只有非常勇敢或绝望的人才应该继续阅读……
That being said, the problem is that the x position of the labels are set when the drawing is rendered (I have not looked into that part of the code, but that is my understanding). So everything you do with set_x() is overridden later. However, there is a way around that: you can monkey patch set_x for certain ticks so that the labels are not drawn where the renderer wants to draw them:
话虽如此,问题是在渲染绘图时设置了标签的 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 )
You can do this selectively only for the labels you want to shift and you can of course also use a different shift for every label.
您可以仅对要移动的标签有选择地执行此操作,当然您也可以为每个标签使用不同的移动。
If anybody knows how to do this on a lower madness level, I would be very interested...
如果有人知道如何在较低的疯狂水平上做到这一点,我会非常感兴趣......
回答by scottlittle
Another way of doing a horizontal alignment:
另一种进行水平对齐的方法:
plt.xticks(ha='left')