3

私はmatplotlibを使用してこのような棒グラフを生成しようとしています

1

ただし、黒いバーの上の数字は上軸線を超えていることに注意してください。ax.relim()、、、ax.autoscale()を使用してax.autoscale_view()この問題を修正しようとしましたが、成功しませんでした。

私の質問は、テキスト+長方形の高さを手動で計算したり、適切にサイズを変更したりせずに、ax.textによって表示されるテキストのサイズを考慮して軸のサイズをきれいに取得する方法はありますか?

Python2.7.3とMatplotlib1.3.xを使用しています

編集:

一部のレンダラーハックから取得したテキストサイズ情報を使用してウィンドウのサイズを手動で変更すると、この問題が解決します。コードを以下に示します。

#!/usr/bin/env python

import matplotlib.pyplot as plt

categoryList = ['F', 'L', 'M', 'T', 'W']
categoryColors = {'C': 'y', 'B': 'r', 'F': 'g', 'M': 'b', 'L': 'm', 'T': 'c', 'W': 'k'}
categoryNames = {'C': 'foo1', 'B': 'foo2', 'F': 'foo3', 'M': 'foo4', 'L': 'foo5', 'T': 'foo6', 'W': 'foo7'}
timeList = [60, 165, 60, 10, 570]
fig = plt.figure()
ax = fig.add_subplot(111)
width = 0.35

legendColors = []
legendNames = []
texts = [] 
for ind in range(len(categoryList)):
    category = categoryList[ind]
    rects = ax.bar([ind],timeList[ind],width,color=categoryColors[category],align="center")
    legendColors.append(rects[0])
    legendNames.append(categoryNames[category])

    # Add the text for the number on top of the bar
    for rect in rects:
        texts.append(ax.text(rect.get_x()+rect.get_width()/2,1.05*rect.get_height(),'%d' % timeList[ind],
                    ha='center',va='bottom'))
# The x axis indices
ind = range(0,len(categoryList))

ax.set_ylabel("Time (Minutes)")
ax.set_xlabel("Category")
ax.set_xticks(ind)
ax.set_xticklabels(categoryList)
lgd = ax.legend(legendColors,legendNames,bbox_to_anchor=(1.0, 1.0), loc=2, borderaxespad=0.3)

# Epic hacks for getting renderer
fig.savefig('foo.png',bbox_extra_artists=(lgd,),bbox_inches='tight')
renderer = fig.axes[0].get_renderer_cache()

window_bbox_list = [t.get_window_extent(renderer) for t in texts]
data_bbox_list = [window_bbox.transformed(ax.transData.inverted()) for window_bbox in window_bbox_list]
data_coords_list = [data_bbox.extents for data_bbox in data_bbox_list]
height_list = [coordEntry[-1] for coordEntry in data_coords_list]
max_height = max(height_list)
fig.axes[0].set_ylim(top=max_height*1.05)
fig.savefig('foo.png',bbox_extra_artists=(lgd,),bbox_inches='tight')
4

1 に答える 1

1

テキストは、描画する軸からほとんど独立したライブを持つオブジェクトであるため、クリーンで自動化された方法があるとは思いません。実際、図全体を描くまで、実際の寸法はありません...

この方法は、プロットに追加したすべてのテキストを追跡することです。たとえば、次のようにします。

texts = []
for your_element in your_cycle:
    do something
    t = ax.text(your_text_params)
    texts.append(t)

次に、テキストの最も高い到達点を見つける必要があります。これを行うには、ウィンドウ座標情報を抽出し、それらをデータ座標に変換する必要があります。これを行う前に、図を描く必要があります。そうしないと、テキストがまだ決定されていません(誰かがよく知っている場合は、私を訂正してください)。

plt.draw()
window_bbox = [t.get_window_extent()  for t in texts]
data_bbox =   [ b.transformed(ax.transData.inverted()) for b in window_bbox ]
data_coords = [ b.extents for b in data_bbox ]

座標範囲を取得した後、各ボックスの最大値とそれらの間の最大値を抽出し、境界線をそれより少し大きく設定します

max_height = [ e[-1] for e in data_coords ]
top = max(max_height)
ax.set_ylim(ymax=top*1.05)
于 2012-12-04T23:26:37.257 に答える