Matplotlib/pyplot:自动调整y轴的单位 [英] Matplotlib/pyplot: Auto adjust unit of y Axis

查看:154
本文介绍了Matplotlib/pyplot:自动调整y轴的单位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想修改以下所示图的Y轴单位.对于大数字,最好使用 M(百万)、k(千)等单位.例如,y 轴应如下所示:50k、100k、150k 等.

下图由以下代码片段生成:

  plt.autoscale(enable = True,axis ='both')plt.title("TTL 分布")plt.xlabel('TTL值')plt.ylabel('数据包数量')y = graphy # 来自 sqlite 查询的数据x = graphx#sqlite查询中的数据宽度= 0.5plt.bar(x,y,width,align ='center',linewidth = 2,color ='red',edgecolor ='red')无花果 = plt.gcf()plt.show()

我看到了此处. FuncFormatter 专门用于根据刻度标签的位置和值提供自定义刻度标签的目的.实际上,在matplotlib示例集合中有一个

I would like to modify the Y axis unit of the plot indicated below. Preferable would be the use of units like M (Million), k (Thousand) for large numbers. For example, the y Axis should look like: 50k, 100k, 150k, etc.

The plot below is generated by the following code snippet:

plt.autoscale(enable=True, axis='both')
plt.title("TTL Distribution")
plt.xlabel('TTL Value')
plt.ylabel('Number of Packets')
y = graphy  # data from a sqlite query
x = graphx  # data from a sqlite query
width = 0.5
plt.bar(x, y, width, align='center', linewidth=2, color='red', edgecolor='red')
fig = plt.gcf()
plt.show()

I saw this post and thought I could write my own formatting function:

def y_fmt(x, y):
    if max_y > 1000000:
        val = int(y)/1000000
        return '{:d} M'.format(val)
    elif max_y > 1000:
        val = int(y) / 1000
        return '{:d} k'.format(val)
    else:
        return y

But I missed that there is no plt.yaxis.set_major_formatter(tick.FuncFormatter(y_fmt)) function available for the bar plot I am using.

How I can achieve a better formatting of the Y axis?

[]

解决方案

In principle there is always the option to set custom labels via plt.gca().yaxis.set_xticklabels().

However, I'm not sure why there shouldn't be the possibility to use matplotlib.ticker.FuncFormatter here. The FuncFormatter is designed for exactly the purpose of providing custom ticklabels depending on the ticklabel's position and value. There is actually a nice example in the matplotlib example collection.

In this case we can use the FuncFormatter as desired to provide unit prefixes as suffixes on the axes of a matplotlib plot. To this end, we iterate over the multiples of 1000 and check if the value to be formatted exceeds it. If the value is then a whole number, we can format it as integer with the respective unit symbol as suffix. On the other hand, if there is a remainder behind the decimal point, we check how many decimal places are needed to format this number.

Here is a complete example:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import FuncFormatter

def y_fmt(y, pos):
    decades = [1e9, 1e6, 1e3, 1e0, 1e-3, 1e-6, 1e-9 ]
    suffix  = ["G", "M", "k", "" , "m" , "u", "n"  ]
    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:
                    print val, signf
                    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
    return y


fig, ax = plt.subplots(ncols=3, figsize=(10,5))

x = np.linspace(0,349,num=350) 
y = np.sinc((x-66.)/10.3)**2*1.5e6+np.sinc((x-164.)/8.7)**2*660000.+np.random.rand(len(x))*76000.  
width = 1

ax[0].bar(x, y, width, align='center', linewidth=2, color='red', edgecolor='red')
ax[0].yaxis.set_major_formatter(FuncFormatter(y_fmt))

ax[1].bar(x[::-1], y*(-0.8e-9), width, align='center', linewidth=2, color='orange', edgecolor='orange')
ax[1].yaxis.set_major_formatter(FuncFormatter(y_fmt))

ax[2].fill_between(x, np.sin(x/100.)*1.7+100010, np.cos(x/100.)*1.7+100010, linewidth=2, color='#a80975', edgecolor='#a80975')
ax[2].yaxis.set_major_formatter(FuncFormatter(y_fmt))

for axes in ax:
    axes.set_title("TTL Distribution")
    axes.set_xlabel('TTL Value')
    axes.set_ylabel('Number of Packets')
    axes.set_xlim([x[0], x[-1]+1])

plt.show()

which provides the following plot:

这篇关于Matplotlib/pyplot:自动调整y轴的单位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆