使页面上所有子图的x轴长度相同

时间:2017-04-19 22:25:38

标签: python python-2.7 matplotlib seaborn subplot

我是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')

2 个答案:

答案 0 :(得分:2)

除非您使用特定宽高比的轴(如在imshow图中或通过调用.set_aspect("equal")),轴所占用的空间应仅取决于沿该方向的图形大小和设置的间距这个数字。

因此,您几乎要求默认行为,并且唯一阻止您获取的行为是您在bbox_inches='tight'命令中使用savefig

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)

答案 1 :(得分:0)

要获得子图的匹配x轴(每个子图的x轴长度相同),您需要在子图之间共享x轴。

请参阅此处的示例https://matplotlib.org/examples/pylab_examples/shared_axis_demo.html