2017-12-14 5 views
2

私はDataFrameから簡単な棒グラフを作成しています。 (シリーズおよびデータフレーム上のプロット法がpyplot.plotの周りだけの単純なラッパーである)なぜpyplot.plot()はwidth = 1、height = 1の追加のRectangleを作成しますか?

import pandas as pd 
import matplotlib as mpl 

df = pd.DataFrame({'City': ['Berlin', 'Munich', 'Hamburg'], 
       'Population': [3426354, 1260391, 1739117]}) 
df = df.set_index('City') 

ax = df.plot(kind='bar') 

これは、生成されたプロット
enter image description here

今、私は個々のバーにアクセスしたいです。

Rectangle(xy=(-0.25, 0), width=0.5, height=3.42635e+06, angle=0) 
Rectangle(xy=(0.75, 0), width=0.5, height=1.26039e+06, angle=0) 
Rectangle(xy=(1.75, 0), width=0.5, height=1.73912e+06, angle=0) 
Rectangle(xy=(0, 0), width=1, height=1, angle=0) 

私はここでの唯一の3長方形を期待する:そして、私が気づいたことは、幅= 1と追加のバー(長方形)、= 1

rects = [rect for rect in ax.get_children() if isinstance(rect, mpl.patches.Rectangle)] 
for r in rects: 
    print(r) 

出力の高さがあるということです。第四の目的は何ですか?

+1

画像へのリンクを投稿してください。誰かがあなたのためにそれを修正します。 –

答えて

1

第4の四角形は、Axisサブプロットの境界ボックスです。
これはPyplotがバウンディングボックスを処理する方法の成果物です.Pandasに固有のものではありません。例えば、通常のPyplotでプロット:

f, ax = plt.subplots() 
ax.bar(range(3), df.Population.values) 
rects = [rect for rect in ax.get_children() if isinstance(rect, mpl.patches.Rectangle)] 
for r in rects: 
    print(r) 

はまだ4つの長方形になり:

Rectangle(-0.4,0;0.8x3.42635e+06) 
Rectangle(0.6,0;0.8x1.26039e+06) 
Rectangle(1.6,0;0.8x1.73912e+06) 
Rectangle(0,0;1x1) 

あり、この余分な長方形を指しPyplot tight layout docsの行だ(とも、なぜその座標は(0,0),(1,1)あるそれは。

...サブプロットが内部に収まる境界ボックスを指定します。座標は正規化されたFigure coordiでなければなりませんデフォルトは(0、0、1、1)です。

はおそらくより徹底的このアーキテクチャについて説明matplotlibのドキュメントのより正式な部分がありますが、私はナビゲートし、それらのドキュメントは難しい、これは私が思い付くことが最高です。

+0

清算をありがとう。だから、プロットのバーにアクセスしたいのであれば、バウンディングボックスの四角形を手動で削除する必要があります。 背景:ここに記載されている機能を使用したかったのです http://composition.al/blog/2015/11/29/a-better-way-to-add-labels-to-bar-charts-with-matplotlib/ – killakalle

+0

リンクした 'autolabel()'関数で 'height = rect.get_height()'の後に 'if height> 1:'のようなもので無視することができます。 –

+0

あなたはこの回答から何かを探していますか? –

2

あなたは興味のあるものを得るために軸のすべての子供を混乱させたくありません。軸に棒グラフしかない場合、ax.patchesは軸に長方形を与えます。

バーのラベル付けに関して、リンクされた物品は最良の選択ではないかもしれません。これは、手動でラベルの距離を計算することを主張していますが、これは実際には有用ではありません。代わりに、引数textcoords="offset points"plt.annotationを使用して、バートップに比べていくつかの点でアノテーションをオフセットするだけです。

import pandas as pd 
import matplotlib.pyplot as plt 

df = pd.DataFrame({'City': ['Berlin', 'Munich', 'Hamburg'], 
       'Population': [3426354, 1260391, 1739117]}) 
df = df.set_index('City') 

ax = df.plot(kind='bar') 


def autolabel(rects, ax): 
    for rect in rects: 
     x = rect.get_x() + rect.get_width()/2. 
     y = rect.get_height() 
     ax.annotate("{}".format(y), (x,y), xytext=(0,5), textcoords="offset points", 
        ha='center', va='bottom') 

autolabel(ax.patches,ax) 

ax.margins(y=0.1) 
plt.show() 

enter image description here

最後に注釈を作成するために、プロットに図形を使用すると、まだ最適な選択ではないかもしれないことに注意してください。代わりになぜデータそのものを使用しないのですか?

import pandas as pd 
import matplotlib.pyplot as plt 

df = pd.DataFrame({'City': ['Berlin', 'Munich', 'Hamburg'], 
       'Population': [3426354, 1260391, 1739117]}) 

ax = df.plot(x = "City", y="Population", kind='bar') 

def autolabel(s, ax=None, name=""): 
    x = s.name 
    y = s[name] 
    ax.annotate("{}".format(y), (x,y), xytext=(0,5), textcoords="offset points", 
       ha='center', va='bottom') 

df.apply(autolabel, axis=1, ax=ax, name="Population") 

ax.margins(y=0.1) 
plt.show() 

これは、上記と同じプロットを生成します。

関連する問題