0

今天,当我尝试使用 matplotlib add_subplot 函数将多个绘图组合成一个图形时,我几乎整天都在苦苦挣扎。

我可以单独绘制每个图,但是当我将它们结合起来时,我会遇到这个问题。这是复制此值错误的简化代码。

from matplotlib import  pyplot as plt
import numpy as np
import os

def plot_in_subplots():
    fig= plt.figure(figsize=(15, 10))

    axis1=fig.add_subplot(311)
    # Uncomment line below to replicate ValueError: Image size of 3719x61904113 pixels is too large. It must be less than 2^16 in each direction.
    # axis2=fig.add_subplot(312)

    plot_bar_plot_in_given_axis(axis1)
    # plot_in_given_axis(axis2)

    figFile = os.path.join('/Users/burcakotlu/Desktop/Test_subplot.png')
    fig.savefig(figFile, dpi=100, bbox_inches="tight")
    plt.cla()
    plt.close(fig)

def plot_in_given_axis(ax):
    xticklabels_list = ['a','b','c','d','e','f'] * 6
    rows=['row1']

    ax.set_xlim([0, 36])
    ax.set_xticklabels([])

    ax.tick_params(axis='x', which='minor', length=0, labelsize=35)
    ax.set_xticks(np.arange(0, 36, 1))
    ax.set_xticks(np.arange(0, 36, 1) + 0.5, minor=True)
    ax.set_xticklabels(xticklabels_list, minor=True)

    ax.xaxis.set_label_position('top')
    ax.xaxis.set_ticks_position('top')

    plt.tick_params(
        axis='x',  # changes apply to the x-axis
        which='major',  # both major and minor ticks are affected
        bottom=False,  # ticks along the bottom edge are off
        top=False)  # labels along the bottom edge are off

    ax.set_ylim([0, len(rows)])
    ax.set_yticklabels([])

    ax.tick_params(axis='y', which='minor', length=0, labelsize=40)

    ax.set_yticks(np.arange(0, len(rows), 1))
    ax.set_yticks(np.arange(0, len(rows), 1) + 0.5, minor=True)
    ax.set_yticklabels(rows, minor=True)  # fontsize

    plt.tick_params(
        axis='y',  # changes apply to the x-axis
        which='major',  # both major and minor ticks are affected
        left=False)  # labels along the bottom edge are off

    ax.grid(which='major', color='black', zorder=3)

def plot_bar_plot_in_given_axis(ax):
    x_axis_labels = ['a', 'b', 'c', 'd', 'e', 'f']
    real_values1 = [266655.0, 0.0, 14072.0, 4137.0, 6752.5, 0.0]
    real_values2 = [273342.5, 0.0, 12598.5, 4240.0, 7425.5, 0.0]
    unreal_values1 = [326188.16, 0.0, 15828.42, 4666.825000000001, 8109.87, 0.0]
    unreal_values2 = [344462.07, 0.0, 16368.664999999999, 5180.2, 8721.64, 0.0]
    q_values = [2.5309603790195403e-28, 1.0, 1.8194829804783173e-33, 0.003603381046779825, 1.0, 1.0]
    name1 = 'X'
    name2 = 'Y'
    color1 = 'r'
    color2 = 'b'
    width = 0.1

    ind = np.arange(len(x_axis_labels))
    legend=None
    rects3=None
    rects4=None

    rects1 = ax.bar(ind, real_values1, width=width, edgecolor='black', color=color1)
    rects2 = ax.bar(ind + width, real_values2, width=width, edgecolor='black', color=color2)

    if ((unreal_values1 is not None) and unreal_values1):
        rects3 = ax.bar(ind+ 2*width, unreal_values1, width=width, edgecolor='black', color=color1, hatch = 'X')
    if ((unreal_values2 is not None) and unreal_values2):
        rects4 = ax.bar(ind +3*width, unreal_values2, width=width, edgecolor='black', color=color2, hatch = 'X')

    ax.tick_params(axis='x', labelsize=35)
    ax.tick_params(axis='y', labelsize=35)

    locs, labels = plt.yticks()
    ax.set_ylim(0, locs[-1] + 5000)
    ax.set_title('%s vs. %s' %(name1,name2), fontsize=20,fontweight='bold')
    ax.set_xticklabels(x_axis_labels, fontsize=35)
    plt.ylabel('Y axis label', fontsize=35, fontweight='normal')

    ax.set_xticks(ind + (3 * width) / 2)
    realStrand1Name = 'Real %s' % (name1)
    realStrand2Name = 'Real %s' % (name2)
    simulationsStrand1Name = 'Unreal %s' % (name1)
    simulationsStrand2Name = 'Unreal %s' % (name2)
    if ((rects1 is not None) and (rects2 is not None) and (rects3 is not None) and (rects4 is not None)):
        if ((len(rects1) > 0) and (len(rects2) > 0) and (len(rects3) > 0) and (len(rects4) > 0)):
            legend = ax.legend((rects1[0], rects2[0], rects3[0], rects4[0]),
                               (realStrand1Name, realStrand2Name, simulationsStrand1Name, simulationsStrand2Name),prop={'size': 25}, ncol=1, loc='best')

    ax.set_facecolor('white')
    ax.spines["bottom"].set_color('black')
    ax.spines["left"].set_color('black')
    ax.spines["top"].set_color('black')
    ax.spines["right"].set_color('black')

    if (legend is not None):
        frame = legend.get_frame()
        frame.set_facecolor('white')
        frame.set_edgecolor('black')

    if q_values is not None:
        for q_value, rect1, rect2 in zip(q_values,rects1,rects2):
            # Get X and Y placement of label from rect.
            y_value = max(rect1.get_height(),rect2.get_height())
            x_value = rect1.get_x() + rect1.get_width()

            space = 3
            va = 'bottom'
            if y_value < 0:
                space *= -1
                va = 'top'

            if ((q_value is not None) and (q_value)<=0.05):
                plt.annotate(
                    '***',  # Use `label` as label
                    (x_value, y_value),  # Place label at end of the bar
                    xytext=(0, space),  # Vertically shift label by `space`
                    textcoords="offset points",  # Interpret `xytext` as offset in points
                    ha='center',  # Horizontally center label
                    va=va,
                    fontsize=20) # Vertically align label differently for

plot_in_subplots()

请取消注释此行以复制ValueError: Image size of 3719x61904113 像素太大。每个方向必须小于 2^16

axis2=fig.add_subplot(312)

这是我想使用add_subplot组合的图 在此处输入图像描述

在此处输入图像描述

4

1 回答 1

0

我已经升级到 Matplotlib 3.4.2。我将 plt.xxx 更改为 ax.xxx(面向对象)并使用 gridspec,我快到了。谢谢。

from matplotlib import  pyplot as plt
from matplotlib import gridspec
import numpy as np
import os

def plot_in_subplots():
    fig= plt.figure(figsize=(30, 10))


    gs = gridspec.GridSpec(10, 4, width_ratios=[1,1,1,1], height_ratios=[1, 1, 1, 1, 1, 1, 1, 1, 1, 1])
    axis1 = plt.subplot(gs[0:7, 1:3])
    axis2 = plt.subplot(gs[9, :])
    # bottom_left_axis = plt.subplot(gs[-1,0])
    # bottom_right_axis = plt.subplot(gs[-1,-1])

    # axis1=fig.add_subplot(211)
    # axis2=fig.add_subplot(212)

    plot_bar_plot_in_given_axis(axis1)
    plot_in_given_axis(axis2)

    figFile = os.path.join('/Users/burcakotlu/Desktop/Test_subplot.png')
    fig.savefig(figFile, dpi=100, bbox_inches="tight")
    plt.cla()
    plt.close(fig)

def plot_in_given_axis(ax):
    xticklabels_list = ['a','b','c','d','e','f'] * 6
    rows=['row1']

    ax.set_xlim([0, 36])
    ax.set_xticklabels([])

    ax.tick_params(axis='x', which='minor', length=0, labelsize=35)
    ax.set_xticks(np.arange(0, 36, 1))
    ax.set_xticks(np.arange(0, 36, 1) + 0.5, minor=True)
    ax.set_xticklabels(xticklabels_list, minor=True)

    ax.xaxis.set_label_position('top')
    ax.xaxis.set_ticks_position('top')

    ax.tick_params(
        axis='x',  # changes apply to the x-axis
        which='major',  # both major and minor ticks are affected
        bottom=False,  # ticks along the bottom edge are off
        top=False)  # labels along the bottom edge are off

    ax.set_ylim([0, len(rows)])
    ax.set_yticklabels([])

    ax.tick_params(axis='y', which='minor', length=0, labelsize=40)

    ax.set_yticks(np.arange(0, len(rows), 1))
    ax.set_yticks(np.arange(0, len(rows), 1) + 0.5, minor=True)
    ax.set_yticklabels(rows, minor=True)  # fontsize

    ax.tick_params(
        axis='y',  # changes apply to the x-axis
        which='major',  # both major and minor ticks are affected
        left=False)  # labels along the bottom edge are off

    ax.grid(which='major', color='black', zorder=3)

def plot_bar_plot_in_given_axis(ax):
    x_axis_labels = ['a', 'b', 'c', 'd', 'e', 'f']
    real_values1 = [266655.0, 0.0, 14072.0, 4137.0, 6752.5, 0.0]
    real_values2 = [273342.5, 0.0, 12598.5, 4240.0, 7425.5, 0.0]
    unreal_values1 = [326188.16, 0.0, 15828.42, 4666.825000000001, 8109.87, 0.0]
    unreal_values2 = [344462.07, 0.0, 16368.664999999999, 5180.2, 8721.64, 0.0]
    q_values = [2.5309603790195403e-28, 1.0, 1.8194829804783173e-33, 0.003603381046779825, 1.0, 1.0]
    name1 = 'X'
    name2 = 'Y'
    color1 = 'r'
    color2 = 'b'
    width = 0.1

    ind = np.arange(len(x_axis_labels))
    legend=None
    rects3=None
    rects4=None

    rects1 = ax.bar(ind, real_values1, width=width, edgecolor='black', color=color1)
    rects2 = ax.bar(ind + width, real_values2, width=width, edgecolor='black', color=color2)

    if ((unreal_values1 is not None) and unreal_values1):
        rects3 = ax.bar(ind+ 2*width, unreal_values1, width=width, edgecolor='black', color=color1, hatch = 'X')
    if ((unreal_values2 is not None) and unreal_values2):
        rects4 = ax.bar(ind +3*width, unreal_values2, width=width, edgecolor='black', color=color2, hatch = 'X')

    ax.tick_params(axis='x', labelsize=35)
    ax.tick_params(axis='y', labelsize=35)

    locs=ax.get_yticks()
    ax.set_ylim(0, locs[-1] + 5000)
    ax.set_title('%s vs. %s' %(name1,name2), fontsize=20,fontweight='bold')
    ax.set_xticklabels(x_axis_labels, fontsize=35)
    ax.set_ylabel('Y axis label', fontsize=35, fontweight='normal')

    ax.set_xticks(ind + (3 * width) / 2)
    realStrand1Name = 'Real %s' % (name1)
    realStrand2Name = 'Real %s' % (name2)
    simulationsStrand1Name = 'Unreal %s' % (name1)
    simulationsStrand2Name = 'Unreal %s' % (name2)
    if ((rects1 is not None) and (rects2 is not None) and (rects3 is not None) and (rects4 is not None)):
        if ((len(rects1) > 0) and (len(rects2) > 0) and (len(rects3) > 0) and (len(rects4) > 0)):
            legend = ax.legend((rects1[0], rects2[0], rects3[0], rects4[0]),
                               (realStrand1Name, realStrand2Name, simulationsStrand1Name, simulationsStrand2Name),prop={'size': 25}, ncol=1, loc='best')

    ax.set_facecolor('white')
    ax.spines["bottom"].set_color('black')
    ax.spines["left"].set_color('black')
    ax.spines["top"].set_color('black')
    ax.spines["right"].set_color('black')

    if (legend is not None):
        frame = legend.get_frame()
        frame.set_facecolor('white')
        frame.set_edgecolor('black')

    if q_values is not None:
        for q_value, rect1, rect2 in zip(q_values,rects1,rects2):
            # Get X and Y placement of label from rect.
            y_value = max(rect1.get_height(),rect2.get_height())
            x_value = rect1.get_x() + rect1.get_width()

            space = 3
            va = 'bottom'
            if y_value < 0:
                space *= -1
                va = 'top'

            if ((q_value is not None) and (q_value)<=0.05):
                ax.annotate(
                    '***',  # Use `label` as label
                    (x_value, y_value),  # Place label at end of the bar
                    xytext=(0, space),  # Vertically shift label by `space`
                    textcoords="offset points",  # Interpret `xytext` as offset in points
                    ha='center',  # Horizontally center label
                    va=va,
                    fontsize=20,
                transform=ax.transAxes) # Vertically align label differently for

plot_in_subplots()

在此处输入图像描述

于 2021-05-12T18:09:27.967 回答