2017-04-19 131 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

相关问题