繁体   English   中英

使用不同大小的 y 轴制作相同的 matplotlib 图

[英]Make identical matplotlib plots with y-axes of different sizes

我正在尝试制作一系列 matplotlib 图,为不同类别的对象绘制时间跨度。 每个绘图都有一个相同的 x 轴和绘图元素,如标题和图例。 但是,每个图中出现的类别不同; 每个图代表一个不同的采样单元,每个单元只包含所有可能类别的一个子集。

我在确定如何设置图形和轴尺寸时遇到了很多麻烦。 水平尺寸应始终保持不变,但垂直尺寸需要缩放到该采样单元中表示的类数。 对于每个绘图,y 轴上每个条目之间的距离应该相等。

似乎我的困难在于我可以使用plt.figure(figsize=(w,h))设置图形的绝对大小(以英寸为单位plt.figure(figsize=(w,h)) ,但我只能设置具有相对尺寸的轴的大小(例如, fig.add_axes([0.3,0.05,0.6,0.85])这会导致我的 x 轴标签在类数量很少时被切断。

这是我想要得到的东西与我得到的东西的 MSPaint 版本。 所需输出与当前输出

这是我使用的代码的简化版本。 希望这足以确定问题/解决方案。

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 = 1
end = 6
interval = 1 # 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)

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")

    ############################################################
    # I think the problem lies here                            
    fig = plt.figure(figsize=(11, len(line_subset.index)*0.25))
    ax = fig.add_axes([0.3,0.05,0.6,0.85])
    ############################################################

    ax.add_collection(lc)
    ax.set_xlim(left=start, right=end)
    ax.set_xticks(xticks)
    ax.xaxis.set_ticks_position('bottom')

    ax.margins(0.05)
    sns.despine(left=True)

    ax.set_yticks(line_subset['order_y'])
    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]
    leg = ax.legend(proxies, ['0-10%', '10-25%', '25-50%', '50-75%', '75-90%', '90-100%'], bbox_to_anchor=(1.0, 0.9), 
              loc='best', ncol=1, labelspacing=3.0, handlelength=4.0, handletextpad=0.5, markerfirst=True, 
              columnspacing=1.0)

    for txt in leg.get_texts():
        txt.set_ha("center") # horizontal alignment of text item
        txt.set_x(-23) # x-position
        txt.set_y(15) # y-position

您可以首先以英寸为单位定义顶部和底部的边距。 使用以英寸为单位的一个数据单位的固定单位可以计算最终数字应该有多大。 然后除以英寸余量由图中高度给出的数字大小为单位的相对容限,这可以使用被提供给数字subplots_adjust ,鉴于副区已被添加与add_subplot

一个最小的例子:

import numpy as np
import matplotlib.pyplot as plt

data = [np.random.rand(i,2) for i in [2,5,8,4,3]]

height_unit = 0.25 #inch
t = 0.15; b = 0.4  #inch

for d in data:
    height = height_unit*(len(d)+1)+t+b
    fig = plt.figure(figsize=(5, height))
    ax = fig.add_subplot(111)
    ax.set_ylim(-1, len(d))
    fig.subplots_adjust(bottom=b/height, top=1-t/height, left=0.2, right=0.9)

    ax.barh(range(len(d)),d[:,1], left=d[:,0], ec="k")
    ax.set_yticks(range(len(d)))

plt.show()

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM