[英]Matplotlib: format offset to standard units
我基本上想要的是代替绘制并具有偏移量10 ^ 8 10 ^ 5或1e8 1e5等,使其具有标准单位,例如10 ^ 3 10 ^ 6 1e3 1e6等。
这可能吗? 如果可以,怎么办?
提前致谢
plt.gca().get_xaxis().get_major_formatter().set_useOffset(False)
你是这个意思吗 (y轴也一样)。 这可能是该问题的重复,其中第二个答案给出的规范描述比我还多。 如果这就是您想要的,请支持他。
编辑
我整个下午都在ax.yaxis.set_scientific(True)
进行此操作,并且似乎设置ax.yaxis.set_scientific(True)
自动胜过任何ax.yaxis.setOffset = False
。 无论您以哪种方式进行操作。 我无法解决这个问题,然后我变得更加恼火。
不过,这是一种变通方法,已测试Py3.4,mpl 1-3-1 win7。
import matplotlib as mpl
import matplotlib.pyplot as plt
import numpy as np
from decimal import Decimal
x_large = np.arange(10, 20000, 100)
y_large = np.arange(10, 20000, 100)
x_small = np.arange(-1, 1, 0.000001)
y_small = np.arange(-1, 1, 0.000001)
metric = [0,1,2,3,6,9, 12, 16]
def format_large(x):
x = float(x)
sx = str(x)
sx = sx.split(".")[0]
if len(sx)-1 in metric:
return "%se%s" % (sx[0], len(sx)-1)
add = - max(exp-len(sx)-1 for exp in metric if exp<len(sx)-1)
return "%se%s" % (sx[0:add], len(sx)-add)
#love thy DRY principle
def check_metric_small(num, exp):
if exp in metric:
return "%se-%s" % (num[0], exp)
add = min(mexp-exp for mexp in metric if mexp>exp)
num = num.ljust(add+1, "0")
return "%se-%s" % (num[0:add+1], exp+add)
def format_small(x):
sx = str(x)
#string representation of numbers after e-4 is
#done in scientific manner 1e-5, 1e-6 ...
if sx.find("e") != -1:
num, exp = sx.split("e")
exp = -int(exp)
return check_metric_small(num, exp)
#numbers up to e-4 are represented in string form
#as is, therefore 0.1, 0.01
s = sx.split(".")[-1]
num = s.strip("0")
exp = len(s)-len(num)
return check_metric_small(num, exp+1)
def formatter(x, p):
if x<0: #make sure we don't send a negative number
res = "-" #rather just tack on the minus sign
x = -x
else: res = ""
if abs(x)<1 and x!=0.0:
return res+format_small(x)
return res+format_large(x)
fig, ax = plt.subplots()
y_formatter = mpl.ticker.FuncFormatter(formatter)
ax.yaxis.set_major_formatter(y_formatter)
ax.plot(x_large,y_large)
plt.show()
重要功能包含在format_large
和format_small
。 它们会将数字四舍五入到metric
列表定义的下一个最接近的较小指数。 就他们自己而言,他们无法处理负数,因此请使用formatter
功能。
在大缩放和非缩放之间切换似乎不会留下任何怪异的效果,也不会超过零。 波纹管是这些功能的要点:
for i in [0, 10, 50, ......]:
print(format_large(i), float(format_large(i)) == i)
0e0 True 5e6 True
1e1 True 5e6 True
5e1 True 50e6 True
5e2 True 500e6 True
5e3 True 50e9 True
50e3 True 500e9 True
500e3 True 5e12 True
for i in [0.05, 0.005, ......]:
print(format_small(i), float(format_small(i)) == i)
5e-2 True 50e-9 True
5e-3 True 5e-9 True
500e-6 True 500e-12 True
50e-6 True 50e-12 True
5e-6 True 50e-12 True
500e-9 True 5000e-16 True
但是请小心,因为我将数字四舍五入,因此只能使用四舍五入的数字进行测试。
对于大数字,发生的是我采用它们的字符串表示形式,即"500.0"
。 数字的长度减去一会得到零/数字的阶数。 如果是公制订单,我将返回最简单的字符串,其中仅包含数字的前导数字及其指数。
如果数字的顺序不是公制,我会找到第一个较低的公制指数: max(exp-len(sx) for exp in metric if exp<len(sx))
(这意味着,我发现指标体系的指数和我所有低于当前数字顺序的指标的当前数字顺序)。 这样可以保证所有差异都是负数,并且最大的数字总是指向最接近的指标。 返回字符串,其中“主”数字的位数超过1,该位数取决于最接近的度量指数和当前数字顺序之间的差。
小数字变得非常复杂,因为有两种情况需要考虑。 当数字大于0.0004
其表示将不会更改。 但是,对于小于此数目的数字,其表示形式将变为科学形式。
我将科学表示形式拆分为字母“ e”,以获得实际数字,即1234
和指数。 如果指数属于公制,则返回字符串。 否则,请为我提供下一个较小的指标索引,并填充数字直到适合为止: mexp-exp for mexp in metric if mexp>exp
(这意味着:对于所有大于当前数字顺序的指数,记住我将当前顺序更改为a)正数,因此,较大的度量指数与较小的实际数相关,请找出电流和度量指数的最小差)。 在返回字符串之前,请用ljust
数字的右侧填充足够的零,以免冒着超出索引范围的错误。
对于非科学表示的小数(即0.000432
,我将其拆分为.
,去除前导零以得到数字432
。 从整个分割数000432
长度中减去的长度确定了我有多少个零。 从那里,我重复查找下一个最接近的指标指数的过程,或者立即返回一个字符串。
函数没有小数位数选项,但是添加它应该是微不足道的。 返回结果并将返回语句修改为类似"%s%se%s" % (sx[0:add], sx[add:ndecimals], len(sx)-add)
之前的if
语句这个问题。
我想说这很有趣。 但这不是:D直到我放弃之前,它都是在手册中大肆破坏。 但是我说我会尽快回覆您,以便您继续。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.