簡體   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