Matplotlib:格式偏移到标准单位

时间:2015-03-02 14:19:37

标签: python matplotlib plot

我基本上想要的不是绘图和偏移10 ^ 8 10 ^ 5或1e8 1e5等以使它们以标准单位如10 ^ 3 10 ^ 6 1e3 1e6等。

这可能吗?如果是这样怎么样?

提前致谢

1 个答案:

答案 0 :(得分:1)

plt.gca().get_xaxis().get_major_formatter().set_useOffset(False)
你是说这个意思吗? (对于y轴也一样)。这是this问题的可能重复,其中第二个答案给出了比我更规范的描述。如果那是你正在寻找的东西,请给他。

修改

我整个下午一直打开和关闭这个,似乎设置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_largeformat_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"。减去1的数字的长度给出了零的数量\数量的顺序。如果它是一个度量单,我返回的最简单的字符串只包含数字的前导数字及其指数。

如果数字的顺序不是度量标准,我会找到第一个较低的度量指数:max(exp-len(sx) for exp in metric if exp<len(sx))(这意味着,找到指标系统的指数与我当前的数字顺序之间的最大差异所有小于当前数字顺序的度量指数)。这可以保证所有差异都是负数,最大数字将始终指向最接近的度量指数。返回字符串&#34; main&#34;数字超过1位数,由最接近的指标指数和当前数字顺序之间的差异确定多少。

小数字变得非常复杂,因为有两种情况需要考虑。当数字大于0.0004时,其表示将不会更改。然而,对于小于此数字的数字,它们的表示将变为科学。

我把科学表示分成了字母&#34; e&#34;得到实际数字,即1234和指数。如果指数属于度量标准系统,则返回该字符串。否则,请获取下一个较小的度量标准索引并填充数字,直到它适合:mexp-exp for mexp in metric if mexp>exp(这意味着:对于所有大于当前数字顺序的指数,并记住我将当前顺序更改为正数,因此更大的度量指数与较小的实际数字相关,找到当前和度量指数的最小差异)。在我返回字符串之前,我使用ljust填充了我的号码右侧的足够零,因此我不会冒险提高索引越界错误。

对于非科学代表的小数字,即0.000432,我将它们分开到.,删除前导零以获得数字432。从整个分割数000432的长度中减去的长度决定了我有多少个零。从那里我重复查找下一个最接近的度量指数的过程,或立即返回一个字符串。

函数没有多个小数选项,但添加它应该是微不足道的。返回结果并将return语句修改为if之前的"%s%se%s" % (sx[0:add], sx[add:ndecimals], len(sx)-add)语句应该处理该问题。

我想说这很有趣。但事实并非如此:在我放弃之前,它通过手册进行了彻底的抨击。但我说我会回复你,所以你去了。