2017-04-19 133 views
1

我是matplotlib的新手,嘗試通過循環創建並保存來自pandas數據框的圖。每個繪圖應該具有相同的x軸,但不同的y軸長度和標籤。創建並保存具有不同y軸長度和標籤的曲線圖時,我沒有問題,但是當我創建曲線圖時,matplotlib重新調整x軸的大小,具體取決於曲線左側的y軸標籤需要多少空間數字。使頁面上所有子圖的x軸長度相同

這些數字是用於技術報告的。我計劃在報告的每個頁面上放置一個,我希望所有的x軸在頁面上佔用相同的空間量。

這是我得到的和我想要的MSPaint版本。 MSPaint-drawn plot examples of the problem and desired solution

希望這是足夠的代碼來幫助。我確定有很多非最優化的部分。

import pandas as pd 
import matplotlib.pyplot as plt 
import pylab as pl 
from matplotlib import collections as mc 
from matplotlib.lines import Line2D 
import seaborn as sns 

# elements for x-axis 
start = -1600 
end = 2001 
interval = 200 # x-axis tick interval 
xticks = [x for x in range(start, end, interval)] # create x ticks 

# items needed for legend construction 
lw_bins = [0,10,25,50,75,90,100] # bins for line width 
lw_labels = [3,6,9,12,15,18] # line widths 
def make_proxy(zvalue, scalar_mappable, **kwargs): 
    color = 'black' 
    return Line2D([0, 1], [0, 1], color=color, solid_capstyle='butt', **kwargs) 

# generic image ID 
img_path = r'C:\\Users\\user\\chart' 
img_ID = 0 

for line_subset in data: 
    # create line collection for this run through loop 
    lc = mc.LineCollection(line_subset) 

    # create plot and set properties 
    sns.set(style="ticks") 
    sns.set_context("notebook") 
    fig, ax = pl.subplots(figsize=(16, len(line_subset)*0.5)) # I want the height of the figure to change based on number of labels on y-axis 
                   # Figure width should stay the same 
    ax.add_collection(lc) 
    ax.set_xlim(left=start, right=end) 
    ax.set_xticks(xticks) 
    ax.set_ylim(0, len(line_subset)+1) 
    ax.margins(0.05) 
    sns.despine(left=True) 
    ax.xaxis.set_ticks_position('bottom') 
    ax.set_yticks(line_subset['order']) 
    ax.set_yticklabels(line_subset['ylabel']) 
    ax.tick_params(axis='y', length=0) 

    # legend 
    proxies = [make_proxy(item, lc, linewidth=item) for item in lw_labels] 
    ax.legend(proxies, ['0-10%', '10-25%', '25-50%', '50-75%', '75-90%', '90-100%'], bbox_to_anchor=(1.05, 1.0), 
       loc=2, ncol=2, labelspacing=1.25, handlelength=4.0, handletextpad=0.5, markerfirst=False, 
       columnspacing=1.0) 

    # title 
    ax.text(0, len(line_subset)+2, s=str(img_ID), fontsize=20) 

    # save as .png images 
    plt.savefig(r'C:\\Users\\user\\Desktop\\chart' + str(img_ID) + '.png', dpi=300, bbox_inches='tight') 

回答

0

爲了獲得匹配的副區x軸(相同的x軸長度對每個副區),則需要共享副區之間的x軸。

看到這裏https://matplotlib.org/examples/pylab_examples/shared_axis_demo.html

+0

調整的插曲之外的間距是否有存儲x軸的方式,以便我可以在循環的下一次運行中使用它?我不想把所有的情節都放在一個連續的數字上;他們需要保存爲單獨的.png文件。 – jdep

+0

您可以在臨時變量中存儲x個限制。讓我們從第零次運行開始,並將其應用於下一次運行(第一次運行)。但是你可能會遇到這樣的問題,即第二次運行時,你將會從第一次運行中採用限制。你可能不希望這樣。 – plasmon360

2

的例子除非你(在imshow情節或通過調用.set_aspect("equal")等)使用具體定義的縱橫尺寸比的一個軸,由軸所佔用的空間應該只依賴於沿該圖中的尺寸方向和間距設置爲圖形。

因此,您幾乎要求默認行爲,唯一阻止您獲取的東西是您在savefig命令中使用bbox_inches='tight'

bbox_inches='tight'會改變圖的大小!所以不要使用它,軸的大小保持不變。 `

根據我對這個問題的理解,你的數字大小,定義爲figsize=(16, len(line_subset)*0.5)似乎有意義。所以剩下的就是確保圖中的軸是你想要的大小。你可以做到這一點通過手動將其使用fig.add_axes

fig.add_axes([left, bottom, width, height]) 

其中left, bottom, width, height在圖座標範圍從0到1,或者,你可以使用subplots_adjust

plt.subplots_adjust(left, bottom, right, top) 
+0

這就是我不需要批評我發現的一些代碼。然而,當我拿走'bbox_inches ='tight''時,我的y軸標籤只有在我設置'figsize'爲一個巨大的x值(> 25英寸)時纔會完全顯示。我能以某種方式將它全部變成8.5x11英寸的尺寸嗎? – jdep

+0

我更新了答案。這對你有幫助嗎? – ImportanceOfBeingErnest

相關問題