在matplotlib轴上设置科学限制后,调整指数文本 [英] Adjust exponent text after setting scientific limits on matplotlib axis
问题描述
目前,如果我将matplotlib的y轴ticklabel设置为科学模式,它会以1e-5
At the moment if I set matplotlib y axis ticklabels to scientific mode it gives me an exponent at the top of the y axis of the form 1e-5
我想将其调整为读取r'$\mathregular{10^{-5}}$'
,以便打印出精美的文字.
I'd like to adjust this to read r'$\mathregular{10^{-5}}$'
so that it prints out nicely.
这是我的示例代码:
# Create a figure and axis
fig, ax = plt.subplots()
# Plot 100 random points
# the y values of which are very small
ax.scatter(np.random.rand(100), np.random.rand(100)/100000.0)
# Set the y limits appropriately
ax.set_ylim(0, 1/100000.0)
# Change the y ticklabel format to scientific format
ax.ticklabel_format(axis='y', style='sci', scilimits=(-2, 2))
# Get the offset value
offset = ax.yaxis.get_offset_text()
# Print it out
print '1st offset printout: {}'.format(offset)
# Run plt.tight_layout()
plt.tight_layout()
# Print out offset again - you can see the value now!
print '2nd offset printout: {}'.format(offset)
# Change it to latex format
offset.set_text(r'$\mathregular{10^{-5}}$')
# Print it out
print '3rd offset printout: {}'.format(offset)
# Add some text to the middle of the figure just to
# check that it isn't the latex format that's the problem
ax.text(0.5, 0.5/100000.0, r'$\mathregular{10^{-2}}$')
# And show the figure
plt.show()
我的输出如下:
1st offset printout: Text(0,0.5,u'')
2nd offset printout: Text(0,636.933,u'1e\u22125')
3rd offset printout: Text(0,636.933,u'$\\mathregular{10^{-5}}$')
您可以在此处找到代码和输出图.
You can find the code and output figure here.
有两个奇怪的地方:一个是我无法覆盖y轴顶部的1e-5(这是目标),另一个是我必须运行plt.tight_layout()
才能使看到该unicode值作为偏移量.
There are two oddities: One is that I can't overwrite the 1e-5 at the top of the y axis (which is the goal), and the other is that I have to run plt.tight_layout()
in order to even see that unicode value as the offset.
谁能告诉我我要去哪里错了?
Can anyone tell me where I'm going wrong?
谢谢
原始问题并未明确说明我想自动检测ticklabel_format
当前计算的指数.因此,与其将设置的字符串传递给偏移文本,不如将其自动检测到该值并相应地调整乳胶字符串.
The original question didn't make clear that I'd like to automatically detect the exponent as is currently calculated by ticklabel_format
. So instead of passing a set string to the offset text it should automatically detect that value and adjust the latex string accordingly.
推荐答案
以@edsmith的答案为基础,一种可能的解决方法是我要获取偏移文本,将其转换为乳胶字符串,然后关闭偏移并在轴的顶部添加该字符串.
Building on @edsmith's answer one possible work around which does what I'd like is to get the offset text, convert it to a latex string, turn off the offset and add in that string at the top of the axis.
def format_exponent(ax, axis='y'):
# Change the ticklabel format to scientific format
ax.ticklabel_format(axis=axis, style='sci', scilimits=(-2, 2))
# Get the appropriate axis
if axis == 'y':
ax_axis = ax.yaxis
x_pos = 0.0
y_pos = 1.0
horizontalalignment='left'
verticalalignment='bottom'
else:
ax_axis = ax.xaxis
x_pos = 1.0
y_pos = -0.05
horizontalalignment='right'
verticalalignment='top'
# Run plt.tight_layout() because otherwise the offset text doesn't update
plt.tight_layout()
##### THIS IS A BUG
##### Well, at least it's sub-optimal because you might not
##### want to use tight_layout(). If anyone has a better way of
##### ensuring the offset text is updated appropriately
##### please comment!
# Get the offset value
offset = ax_axis.get_offset_text().get_text()
if len(offset) > 0:
# Get that exponent value and change it into latex format
minus_sign = u'\u2212'
expo = np.float(offset.replace(minus_sign, '-').split('e')[-1])
offset_text = r'x$\mathregular{10^{%d}}$' %expo
# Turn off the offset text that's calculated automatically
ax_axis.offsetText.set_visible(False)
# Add in a text box at the top of the y axis
ax.text(x_pos, y_pos, offset_text, transform=ax.transAxes,
horizontalalignment=horizontalalignment,
verticalalignment=verticalalignment)
return ax
请注意,您应该能够通过调用pos = ax_axis.get_offset_text().get_position()
使用偏移文本的位置,但是这些值不是以轴为单位的(它们很可能是像素单位-感谢@EdSmith-因此不是很有用).因此,我只是根据要查看的轴设置了x_pos
和y_pos
值.
Note that you should be able to use the position of the offset text by calling pos = ax_axis.get_offset_text().get_position()
but these values are not in axis units (they're likely pixel units - thanks @EdSmith - and thus not very helpful). Therefore I've just set the x_pos
and y_pos
values according to whichever axis we're looking at.
我还编写了一个小函数来自动检测适当的x和y限制(即使我知道matplotlib有很多不错的方法可以做到这一点).
I also wrote a little function to automatically detect appropriate x and y limits (even though I know that matplotlib has lots of fancy ways of doing this).
def get_min_max(x, pad=0.05):
'''
Find min and max values such that
all the data lies within 90% of
of the axis range
'''
r = np.max(x) - np.min(x)
x_min = np.min(x) - pad * r
x_max = np.max(x) + pad * r
return x_min, x_max
因此,要从问题中更新我的示例(稍作更改以使两个轴都需要指数):
So, to update my example from the question (with a slight change to make both axes need the exponent):
import matplotlib.pylab as plt
import numpy as np
# Create a figure and axis
fig, ax = plt.subplots()
# Plot 100 random points that are very small
x = np.random.rand(100)/100000.0
y = np.random.rand(100)/100000.0
ax.scatter(x, y)
# Set the x and y limits
x_min, x_max = get_min_max(x)
ax.set_xlim(x_min, x_max)
y_min, y_max = get_min_max(y)
ax.set_ylim(y_min, y_max)
# Format the exponents nicely
ax = format_exponent(ax, axis='x')
ax = format_exponent(ax, axis='y')
# And show the figure
plt.show()
可以使用此处
希望对您有帮助!
这篇关于在matplotlib轴上设置科学限制后,调整指数文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!