【问题标题】:Dynamically changing yticks动态变化的 yticks
【发布时间】:2019-04-10 13:52:59
【问题描述】:
def y_ticks(y, pos):
    decades = [1e9, 1e6, 1e3, 1e0 ]
    suffix  = ['B', 'M', 'K', '']
    if y == 0:
        return str(0)
    for i, d in enumerate(decades):
        if np.abs(y) >=d:
            val = y/float(d)
            signf = len(str(val).split('.')[1])
            if signf == 0:
                return '{val:d} {suffix}'.format(val=int(val), suffix=suffix[i])
            else:
                if signf == 1:
                    if str(val).split('.')[1] == '0':
                        return '{val:d} {suffix}'.format(val=int(round(val)), suffix=suffix[i])
                tx = '{'+'val:.{signf}f'.format(signf = signf) +'} {suffix}'
                return tx.format(val=val, suffix=suffix[i])
    return y

我想用简单的方式编写这个函数,它变得复杂理解。我是 python 新手,有人可以帮我写这个。这样做的目的是动态改变 y 刻度

例如:1000000 -> 1M, 1000000000 ->1B

【问题讨论】:

    标签: python python-3.x python-2.7 function matplotlib


    【解决方案1】:

    这就是我将如何简化函数:

    def y_ticks_(y, pos):
        # map to choose suffix
        value_to_suffix = {1e3: ' K', 1e6: ' M', 1e9: ' B'}
        # initialize value and suffix
        value = y
        suffix = ''
        # choose appropriate suffix
        for val in sorted(value_to_suffix):
            # "> 1 - 10 ** -10" is used instead of ">= 1" because of how floats are represented in Python - precision is limited by 15 digits.
            if abs(y / val) > 1 - 10 ** -10:
                value = y / val
                suffix = value_to_suffix[val]
            else:
                break
        # create string from value and suffix
        y_new = '{:.3f}'.format(value).strip('0').strip('.') + suffix
        return y_new
    

    以及原版和修改版的对比:

    print('{:>15}|{:>15}|{:>15}|'.format('value', 'original', 'new'))
    print('-' * 48)
    for val in [10, -5, 102, -200, 1001, -1234, 15200, -22000, 99001,
                1e5, 1e6, 1e7, 1999999, 1999999.99, 1e9]:
        print(
            '{:>15}|{:>15}|{:>15}|'
            .format(val, y_ticks(val, list()), y_ticks_(val, list())))
    

    比较结果:

              value|       original|            new|
    ------------------------------------------------
                 10|            10 |             10|
                 -5|            -5 |             -5|
                102|           102 |            102|
               -200|          -200 |           -200|
               1001|        1.001 K|        1.001 K|
              -1234|       -1.234 K|       -1.234 K|
              15200|         15.2 K|         15.2 K|
             -22000|          -22 K|          -22 K|
              99001|       99.001 K|       99.001 K|
           100000.0|          100 K|          100 K|
          1000000.0|            1 M|            1 M|
         10000000.0|           10 M|           10 M|
            1999999|     1.999999 M|            2 M|
         1999999.99|   1.99999999 M|            2 M|
       1000000000.0|            1 B|            1 B|
    

    编辑。关于 Python 中的浮点数。

    在这段代码中使用>= 1 几乎在任何情况下都不是问题。但是考虑示例:

    a = 0
    a += 1.01 / 2.03
    a -= 1 / 2.03
    a -= .01 / 2.03
    

    a 在所有这些操作之后应该为零,但在我的机器上a 等于-6.938893903907228e-18,因为精度是有限的。当您要检查浮点数之间的相等性时,您必须考虑到这一事实。

    【讨论】:

    • 看起来不错,我仍然对使用 # "> 1 - 10 ** -10" 而不是 ">= 1" 感到困惑,因为 Python 中如何表示浮点数 -精度受限于 15 位 仍然混淆而不是 1 我们需要使用 0.9999999 你有任何基于此的特定 python 文档
    • 你能解释一下吗?
    • Inaddtion if I used 1 as below 'if abs(y / val) > 1:' if input is 1000 -> 输出也是 1000(这使得事情有效在我的用例中)虽然它应该像 1K
    • @Terry 我添加了关于浮动的小例子。简而言之,您可以在此代码中使用>= 1,但如果您在任何编程语言中检查它们之间的相等性,请注意浮点数。
    • stackoverflow.com/questions/53184308/… 可以分享您对这个问题的看法吗?
    猜你喜欢
    • 2018-08-22
    • 1970-01-01
    • 2016-04-02
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    • 2021-12-29
    • 2015-08-11
    • 2011-08-26
    相关资源
    最近更新 更多