基于@edsmith的答案,一种可能的解决方法是获取偏移文本,将其转换为乳胶字符串,关闭偏移并在轴的顶部添加该字符串。
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
and y_pos
根据我们正在查看的轴的值。
我还编写了一个小函数来自动检测适当的 x 和 y 限制(尽管我知道 matplotlib 有很多奇特的方法可以做到这一点)。
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
因此,要更新问题中的示例(稍作更改以使两个轴都需要指数):
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()
可以使用带有显示代码输出的 ipython 笔记本的要点here http://nbviewer.ipython.org/gist/HappyPenguin/85d4483bfc686bdbd52b.
我希望这有帮助!