2012-12-04 40 views
3

我已經嘗試使用matplotlib來產生這樣Matplotlib軸調整大小以容納文本

1

然而的柱狀圖,注意,上述黑條數超過頂軸線。我嘗試過使用ax.relim(),ax.autoscale(),ax.autoscale_view()來糾正這個問題,但沒有成功。

我的問題是:有沒有一種方法可以清楚地獲取軸大小,以解釋由ax.text顯示的文本的大小,而無需手動計算文本+矩形的高度並手動調整大小?

我使用Python 2.7.3和Matplotlib的1.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') 

回答

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 ] 

獲得coordate程度之後,我們提取的每一個盒maximium以及它們之間的最大值,然後將邊框設置爲多一點比

max_height = [ e[-1] for e in data_coords ] 
top = max(max_height) 
ax.set_ylim(ymax=top*1.05) 
+0

優秀的,謝謝!這有效,只需要一點渲染就可以繞過'draw()'的要求,這樣我就可以使用'figure.savefig()'。查看我的編輯完整代碼。 –