2012-03-08 10 views
11

を作成し、私はmatplotlibのを使用して、水平棒グラフを作成するために、次のスニペットaccrossつまずいています:matplotlibのチャート - 水平棒グラフ

import matplotlib 
from pylab import * 

val = 3+10*rand(5) # the bar lengths 
pos = arange(5)+.5 # the bar centers on the y axis 
print pos 
figure(1) 
barh(pos,val, align='center') 
yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')) 
xlabel('Performance') 
title('horizontal bar chart using matplotlib') 
grid(True) 
show() 

を私は次のように上記のスクリプトを変更したい:

  1. メイクをプロットされたバーは「チャンクが少ない」(すなわち、プロットされた水平バーの高さを減少させる)
  2. 同じプロット上に水平バーとして負の数と正の数をプロットする

上記の変更を行うのに役立つヘルプ(コードスニペットまたはリンク)は非常に役に立ちます。私が積み重ねられた水平バー(各ラベルは、3本の積み重ね横棒を持っていたと言う)を作成したい場合はさておき、どのように私は、プロット3積み重ね水平バープロットを行うために上記のコードを修正するのでしょうか?など

[[編集]]

誰かがどのように示している二つの短いコードスニペット投稿できる:例えば、水平バー(その結果の反対側に

  1. 印刷ラベルを第1象限に「負」のラベルのラベルが表示され、第2象限に「正の」バーのラベルが表示されます。

  2. 複数の(例えば2つまたは3つの)水平バーを1つではなくプロットします。 amplesは、一般的にはfirst two images shown here

答えて

21
import matplotlib 
from pylab import * 

val = 3-6*rand(5) # the bar lengths  # changed your data slightly 
pos = arange(5)+.5 # the bar centers on the y axis 
print pos 
figure(1) 
barh(pos,val, align='center',height=0.1) # notice the 'height' argument 
yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')) 

gca().axvline(0,color='k',lw=3) # poor man's zero level 

xlabel('Performance') 
title('horizontal bar chart using matplotlib') 
grid(True) 
show() 

あり、私はfrom pyplot import *を使用しないことをお勧めしたいです。あなたが対話モードにしている場合を除き、オブジェクト指向のアプローチを使用します。

import matplotlib.pyplot as plt 
from numpy.random import rand 
from numpy import arange 

val = 3-6*rand(5) # the bar lengths 
pos = arange(5)+.5 # the bar centers on the y axis 
print pos 

fig = plt.figure() 
ax = fig.add_subplot(111) 
ax.barh(pos,val, align='center',height=0.1) 
ax.set_yticks(pos, ('Tom', 'Dick', 'Harry', 'Slim', 'Jim')) 

ax.axvline(0,color='k',lw=3) # poor man's zero level 

ax.set_xlabel('Performance') 
ax.set_title('horizontal bar chart using matplotlib') 
ax.grid(True) 
plt.show() 

プロットの様々な種類のための良い出発点であるがmatplotlib gallery

+0

ありがとう、これは私が探しているものです。私が気づいたことの1つは、プロット上に(Y軸)ラベルがないことです。負の水平バーの場合は、第1象限にラベルを、第2象限にラベルをそれぞれ付けるようにします。 –

+0

私の知る限り、自動的にはできません。 'text'や' annotate'を使って自動的に行うのは難しくありません。 –

8

ジェーニャで言ったように、あなたはtweekする必要がありますあなたのプロット。それは次にYの位置に応じてティックを計算

    • 入力が辞書に囲まれたデータ、である。一例として

      は、以下のカスタマイズ水平バープロットを生成する関数です。各カテゴリー(人)にある小節数(小節数)、および各カテゴリー間に入れたいスペース。

    • (あなたがそれを指定した場合、別の色で)最終的には、データ測定のそれぞれをプロット

    デフォルトでは、それは右にカテゴリ(人)の名前をプロットしますが、あなたはのことができますコース変更。生成

    import numpy as np 
    import matplotlib.pyplot as plt 
    
    # creation of the data 
    name_list = ['day1', 'day2', 'day3', 'day4'] 
    data = {name: 3+10*np.random.rand(5) for name in name_list} 
    
    colors_list = ['0.5', 'r', 'b', 'g'] #optional 
    
    def customize_barh(data, width_bar=1, width_space=0.5, colors=None): 
        n_measure = len(data)     #number of measure per people 
        n_people = data[data.keys()[0]].size # number of people 
    
        #some calculation to determine the position of Y ticks labels 
        total_space = n_people*(n_measure*width_bar)+(n_people-1)*width_space 
        ind_space = n_measure*width_bar 
        step = ind_space/2. 
        pos = np.arange(step, total_space+width_space, ind_space+width_space) 
    
        # create the figure and the axes to plot the data 
        fig = plt.figure(figsize=(8,6)) 
        ax = fig.add_axes([0.15, 0.15, 0.65, 0.7]) 
    
        # remove top and right spines and turn ticks off if no spine 
        ax.spines['right'].set_color('none') 
        ax.spines['top'].set_color('none') 
        ax.xaxis.set_ticks_position('bottom') 
        ax.yaxis.set_ticks_position('right') # ticks position on the right 
        # postition of tick out 
        ax.tick_params(axis='both', direction='out', width=3, length=6, 
            labelsize=24, pad=8) 
        ax.spines['left'].set_linewidth(3) 
        ax.spines['bottom'].set_linewidth(3) 
    
        # plot the data 
        for i,day in enumerate(data.keys()): 
         if colors == None: 
          ax.barh(pos-step+i*width_bar, data[day], width_bar, #facecolor='0.4', 
            edgecolor='k', linewidth=3) 
         else: 
          ax.barh(pos-step+i*width_bar, data[day], width_bar, facecolor=colors[i], 
            edgecolor='k', linewidth=3) 
    
    
        ax.set_yticks(pos) 
        # you may want to use the list of name as argument of the function to be more 
        # flexible (if you have to add a people) 
        ax.set_yticklabels(('Tom', 'Dick', 'Harry', 'Slim', 'Jim'))   
        ax.set_ylim((-width_space, total_space+width_space)) 
        ax.set_xlabel('Performance', size=26, labelpad=10) 
    
    customize_barh(data, colors=colors_list) 
    plt.savefig('perf.png') 
    plt.show() 
    

    :述べたよう this

  • +0

    コードスニペットありがとう。私が思ったより少し複雑です。まだ、..ほとんど2番目の部分は完全に完了しているthats。上記のプロットの凡例を表示したい場合は、単純にplt.legend()という文を追加するだけで正しいと思っているのですが、私は 'customize_barh'関数を読み直して、 。最後に、最初の部分で説明したようにチャートをプロットする方法を示すスニペットを投稿できますか? (つまり、マイナスバーには第1象限などのラベルが付きます)。 matplotlibでそれを達成する方法は私にはまだ分かりません。 –

    +0

    また、カスタマイズされた横棒グラフのラベルを、デフォルトの権利の代わりに左にプロットするにはどうすればよいですか。ありがとう –

    +0

    @ HomunculusReticulli、関数はあなたができることの一例にすぎません。 「ワンタイムプロット」の場合は、関数内で興味のあるコードを取り出してください。 'ax.yaxis.set_ticks_position( 'right')'は、左にチックを持つように変更したい行です( 'left'に変更します)。あなたが達成したいことに関して、 'ax.text'を使って遊ぶのは、値(正または負)に関してティック位置をどのように交互にするかを理解するのではなく、簡単にするべきです。伝説の場合、 'plt.legend(['d1'、 'd2'、 'd3'、 'd4'])'のようなものが動作します。 – gcalmettes

    1

    を以下のコードは、スニペットは、正の値に対して負の値と右辺のために左側にテキストラベルに注釈を付けるために、テキスト関数を使用する例でありますgcalmettesとZhenyaの両方によって。

    from pylab import setp 
    import numpy as np 
    import matplotlib.pyplot as plt 
    import math 
    
    # creation of the data 
    name_list = ['day1', 'day2', 'day3', 'day4'] 
    data = {name: 3+10*np.random.rand(5) for name in name_list} 
    
    for name in name_list: 
        data[name][0] = data[name][0]*-1 
        data[name][2] = data[name][2]*-1 
    
    colors_list = ['0.5', 'r', 'b', 'g'] #optional 
    
    def customize_barh(data, width_bar=1, width_space=0.5, colors=None): 
        n_measure = len(data)     #number of measure per people 
        n_people = data[data.keys()[0]].size # number of people 
    
        #some calculation to determine the position of Y ticks labels 
        total_space = n_people*(n_measure*width_bar)+(n_people-1)*width_space 
        ind_space = n_measure*width_bar 
        step = ind_space/2. 
        pos = np.arange(step, total_space+width_space, ind_space+width_space) 
        # create the figure and the axes to plot the data 
        fig = plt.figure(figsize=(8,6)) 
        ax = fig.add_axes([0.15, 0.15, 0.65, 0.7]) 
    
        # remove top and right spines and turn ticks off if no spine 
        ax.spines['right'].set_color('none') 
        ax.spines['top'].set_color('none') 
        ax.xaxis.set_ticks_position('bottom') 
        ax.yaxis.set_ticks_position('default') # ticks position on the right 
        # postition of tick out 
        ax.tick_params(axis='both', direction='out', width=3, length=6, 
            labelsize=24, pad=8) 
        ax.spines['left'].set_linewidth(3) 
        ax.spines['bottom'].set_linewidth(3) 
    
        # plot the data 
        for i,day in enumerate(data.keys()): 
         if colors == None: 
          ax.barh(pos-step+i*width_bar, data[day], width_bar, #facecolor='0.4', 
            edgecolor='k', linewidth=3) 
         else: 
          ax.barh(pos-step+i*width_bar, data[day], width_bar, facecolor=colors[i], 
            edgecolor='k', linewidth=3) 
    
    
        ax.set_yticks(pos) 
        # you may want to use the list of name as argument of the function to be more 
        # flexible (if you have to add a people) 
        setp(ax.get_yticklabels(), visible=False)   
        ax.set_ylim((-width_space, total_space+width_space)) 
        ax.set_xlabel('Performance', size=26, labelpad=10) 
        labels_list = ['Tom', 'Dick', 'Harry', 'Slim','Jim'] 
    
        # creation of an array of positive/negative values (based on the values 
        # of the data) that will be used as x values for adding text as side labels 
        side_list = [] 
        for index in range(len(labels_list)): 
         sum = 0 
         for name in name_list: 
          sum+= data[name][index] 
         if math.copysign(1,sum) > 0: 
          side_list.append(16) 
         else: 
          side_list.append(-21) 
        for label in labels_list: 
         plt.text(side_list[labels_list.index(label)], pos[labels_list.index(label)]-0.5, label,fontsize=26) 
    customize_barh(data, colors=colors_list) 
    plt.savefig('perf.png') 
    plt.show() 
    

    これは、与えられた人のために、すべてのバーが正しい側に注釈を付けることにするテキストの負または正する必要があること基づいて動作します。この動作を変更するには、side_listの生成を変更します。

    たとえば、ラベルの位置を特定するバーのしきい値を設定する場合は、指定した名前の値を合計するのではなく、そのしきい値を超えるデータ値をカウントします。 side_listの生成はまた、例を使用することを所与として、データの範囲に調整するために変更する必要があります

    ループしかしながら多くのうち3つのバーのしきい値のEgは

    for index in range(len(labels_list)): 
         count = 0 
          for name in name_list: 
           if data[name][index] > 0: 
            count+= 1 
          if count > 3: 
           side_list.append(16) 
          else: 
           side_list.append(-21) 
    

    なります指定された範囲のランダムデータ。

    例:データに合わせてラベルオフセットを調整する必要があります(side_list.append(16)side_list.append(-21))。

    関連する問題