2016-11-12 117 views
0

以下に示すプロットのY軸単位を変更したいと思います。多くの場合、M(百万)、k(千)などの単位の使用が望ましいでしょう。例えば、Y軸は、次のようになります。など50K、100K、150K、Matplotlib/pyplot:y軸の自動調整単位

の下に次のコードスニペットによって生成されたプロット:

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() 

私はthisポストを見て、私は書くことができると思った私独自のフォーマット機能:

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 

しかし、私は、私が使用していますバープロットのために利用可能なplt.yaxis.set_major_formatter(tick.FuncFormatter(y_fmt))機能がないことを逃しました。

どのようにしてY軸のフォーマットを改善できますか?あなたはかなり接近していた

[TTL Distribution Plot]

答えて

2

原則として、 reは常にplt.gca().yaxis.set_xticklabels()でカスタムラベルを設定するオプションです。

ただし、なぜここにmatplotlib.ticker.FuncFormatterを使用するべきではないかわかりません。 FuncFormatterは、ティックラベルの位置と値に応じて、カスタムティックラベルを提供する目的のために設計されています。 実際にはnice exampleがmatplotlibのサンプルコレクションにあります。

この場合、望みどおりにFuncFormatterを使用して、ユニット接頭辞をmatplotlibプロットの軸に接尾辞として指定することができます。この目的のために、1000の倍数を繰り返し、フォーマットされる値がそれを超えているかどうかを確認します。値が整数の場合は、それぞれの単位記号を接尾辞として整数として整形できます。一方、小数点の後ろに余りがある場合は、この数値の書式設定に必要な小数点以下の桁数を確認します。次のプロットを提供

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() 

:あなたの答えのための

enter image description here

+0

いい例、たくさんのより完全な私の。しかし、 "小数点の後ろに余りがある場合は、小数点以下の桁数を確認する" *と書いていますが、カットオフはやはりランダムです。例えば。 'y_fmt(100100、0)'は '100.1k'を返しますが、' y_fmt(100010,0) 'は' 100k'を返します。 – Bart

+1

@Bart正解!私はその問題を考えましたが、その後それを忘れました。私はこの例を更新しました。その場合、数字は大きくても近くにあります。 – ImportanceOfBeingErnest

+1

組み込みの 'EngFormatter'もあります。これは、非常に似たようなものです。http://matplotlib.org/examples/api/engineering_formatter.html – tacaswell

0

FuncFormatterについての1つの(おそらく)混乱していることは、最初の引数がティック値であり、2番目のティック位置は、(x,yという名前の)y軸に対して混乱する可能性があるということです。わかりやすくするために、以下の例で名前を変更しました。

関数は、文字列

http://matplotlib.org/api/ticker_api.html#matplotlib.ticker.FuncFormatter

実施例二つの入力(目盛り値xと位置pos)に取り、返すべき

import numpy as np 
import matplotlib.pylab as pl 
import matplotlib.ticker as tick 

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

x = np.arange(300) 
y = np.random.randint(0,2000000,x.size) 

width = 0.5 
pl.bar(x, y, width, align='center', linewidth=2, color='red', edgecolor='red') 
pl.xlim(0,300) 

ax = pl.gca() 
ax.yaxis.set_major_formatter(tick.FuncFormatter(y_fmt)) 

enter image description here

+1

おかげ

はここで完全な例です!しかし、ImportanceOfBeingErnestからの回答は、添え字をさらに拡張しているので、「受け入れられた」とマークしました。 – Patrick

関連する問題