我正在使用 python 2.7 在 pyqt 程序中使用 matplotlib 绘制一些大数字。我有一个 y 轴,范围从 1e+18 到 3e+18(通常)。我希望看到每个刻度线都以科学记数法显示值,并保留 2 位小数。例如 2.35e+18 而不是 2e+18,因为 2e+18 和 3e+18 之间的值仍然只读取 2e+18 几个刻度线。这是该问题的示例。
import numpy as np
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16
ax.plot(x,y)
ax.get_xaxis().set_major_formatter(plt.LogFormatter(10, labelOnlyBase=False))
ax.get_yaxis().set_major_formatter(plt.LogFormatter(10, labelOnlyBase=False))
plt.show()
如果您使用
matplotlib.ticker.FormatStrFormatter
而不是 LogFormatter
,这真的很容易做到。以下代码将使用 '%.2e'
: 格式标记所有内容
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
fig = plt.figure()
ax = fig.add_subplot(111)
x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16
ax.plot(x,y)
ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.2e'))
plt.show()
为了在科学计数法中获得格式良好的标签,可以使用
ScalarFormatter
的格式化功能,它使用 MathText (Latex) 并将其应用于标签。
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker
fig, ax = plt.subplots()
x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16
ax.plot(x,y)
f = mticker.ScalarFormatter(useOffset=False, useMathText=True)
g = lambda x,pos : "${}$".format(f._formatSciNotation('%1.10e' % x))
plt.gca().yaxis.set_major_formatter(mticker.FuncFormatter(g))
plt.show()
虽然这在很多情况下可能会有用,但实际上并不能满足问题的要求。要在所有标签上使用相同的数字,可以使用更定制的版本。
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.ticker as mticker
fig, ax = plt.subplots()
x = np.linspace(0, 300, 20)
y = np.linspace(0,300, 20)
y = y*1e16
ax.plot(x,y)
class MathTextSciFormatter(mticker.Formatter):
def __init__(self, fmt="%1.2e"):
self.fmt = fmt
def __call__(self, x, pos=None):
s = self.fmt % x
decimal_point = '.'
positive_sign = '+'
tup = s.split('e')
significand = tup[0].rstrip(decimal_point)
sign = tup[1][0].replace(positive_sign, '')
exponent = tup[1][1:].lstrip('0')
if exponent:
exponent = '10^{%s%s}' % (sign, exponent)
if significand and exponent:
s = r'%s{\times}%s' % (significand, exponent)
else:
s = r'%s%s' % (significand, exponent)
return "${}$".format(s)
# Format with 2 decimal places
plt.gca().yaxis.set_major_formatter(MathTextSciFormatter("%1.2e"))
plt.show()
最近重装电脑后,@ImportanceOfBeingEmest 中描述的
ScalarFormatter
和_formatSciNotation
方法不再有效。我收到以下错误消息。
g = lambda x,pos : "${}$".format(f._formatSciNotation('%1.10e' % x))
AttributeError: 'ScalarFormatter' 对象没有属性 '_formatSciNotation'
按照以下答案的建议,我使用
LogFormatterSciNotation
实现了我的需求。
https://stackoverflow.com/a/74403178/2494226
例子:
from matplotlib.ticker import LogFormatterSciNotation
plt.gca().set_xticks([1E2,3E2,1E3,3E3,1E4,3E4,1E5])
plt.gca().xaxis.set_major_formatter(LogFormatterSciNotation(base=10,minor_thresholds=(10,10)))