簡體   English   中英

Matplotlib 子圖軸在繪制數據后改變大小

[英]Matplotlib subplot axes change size after plotting data

我有一個相當長的程序,我一直在致力於在我的實驗室進行一些數據分析。 它需要一個 csv 文件,並根據輸入 DNA(實際上是 RNA,但在這種情況下無關緊要)的一系列濃度計算一個或多個基因目標的檢測限。

由於要評估的目標數量是可變的,我編寫了兩個函數 - 一個makeplots(targets)返回帶有子圖的圖形(根據我想要的方式排列,取決於有多少)和子圖的軸數組。 經過一些數據處理和計算,我的drawplots(ax[i], x, y, [other variables for less-relevant settings]) function 在循環中調用,該循環遍歷每個目標的數據表數組。

makeplots()工作正常 - 一切都在我想要的地方,形狀很好,等等。但是一旦drawplots()被調用,比例就會扭曲並且情節看起來很糟糕。

下面的代碼不是原始腳本(盡管功能相同)——我刪除了大部分處理和輸入步驟,只定義了變量和 arrays,因為它們在處理一些測試數據時結束。 這僅適用於兩個目標; 我還沒有嘗試過 3+,因為我想先按順序獲得更簡單的情況。

(原諒冗長的導入塊;我只是從真實腳本中復制了它。我有點時間緊迫,不想擺弄導入,以防我刪除了在這個壓縮示例中我實際上仍然需要的導入)

import os
import sys
import time
import math
import scipy
import datetime
import warnings
import collections
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import win32gui as wg
from win32gui import GetWindowText, GetForegroundWindow
from scipy.stats import norm
from tkinter import filedialog
from tkinter import *


actwindow = (GetForegroundWindow())
root = Tk()
root.withdraw()
cbcolors = ['#377eb8', '#f781bf', '#dede00', '#999999',
            '#4daf4a', '#984ea3', '#e41a1c', '#ff7f00',
            '#000000', '#a65628']
params = {'mathtext.default': 'regular'}
plt.rcParams.update(params)

#######################################################
#           create figure and array of axes           #
#######################################################
def makeplots(targets, active=actwindow):
    numsubs = len(targets)
    def rowcnt(y):
        rownumb = (y//3) if y%3 == 0 else (1+(y//3))
        return rownumb
    def colcnt(x):
        if x <= 3: colnumb = x
        elif x == 4: colnumb = 2
        else: colnumb = 3
        return colnumb
    if numsubs >= 1:
        fig, axs = plt.subplots(num='LLoD', nrows=rowcnt(numsubs), ncols=colcnt(numsubs), sharey='row', figsize = [colcnt(numsubs)*5,rowcnt(numsubs)*6], subplot_kw={'adjustable': 'box', 'aspect': 1})
        fig.text(0.04, 0.5, 'Probit score\n    $(\sigma + 5)$', va='center', rotation='vertical', size='18')
    else:
        raise ValueError('Error generating plots -- number of targets must be a positive integer.')
    axs = np.ravel(axs)
    for i, ax in enumerate(axs):
        ax.set_title(f'Limit of Detection: {targets[i]}', size=11)
        ax.grid()
    return fig, axs

#######################################################
#                 draw the actual plots               #
#######################################################
def drawplots(ax, x, y, logans, color1, color2):
    y95 = 6.6448536269514722
    regfun = lambda m, x, b : (m*x) + b
    regression = scipy.stats.linregress(x,y)
    slope, intercept, r = regression.slope, regression.intercept, regression.rvalue
    r2 = r**2

    while True:
        if logans == 'y':
            x_label = '$log_{10}$(input quantity)'
            break
        elif logans == 'n':
            x_label = 'input quantity'
            break
        raise ValueError('Error calling drawplots() - invalid input')

    lod = (y95-intercept)/slope
    xr = [0, lod*1.2]
    yr = [intercept, regfun(slope, xr[1], intercept)]
    regeqn = "y = " + str(f"{slope:.3f}") +"x + " + str(f"{intercept:.3f}")

    ax.set_xlabel(x_label)
    ax.plot(xr, yr, color=color1, linestyle='--') # plot linear regression of data
    ax.plot(lod, y95, marker='o', color=color2, markersize=7) # marks the limit of detection
    ax.plot(xr, [y95,y95], color=color2, linestyle=':') # horiz. line to lod
    ax.plot([lod,lod], [0, 7.1], color=color2, linestyle=':') # vert. line to lod
    ax.plot(x, y, color=color1, marker='x') # plot lod data points
    ax.set_aspect('equal')
    ax.set_xlim(left=0)
    ax.plot()

    return r2, lod, regeqn
#######################################################
#                      main script                    #
#######################################################
numTar = 2
logans, logconv = 'y', 'n'
targets = ['target1','target2']
qtys = np.array([6, 5, 4.7, 4, 3.7, 3, 2.7, 2.4, 2, 1.7])
prop = np.array([1, 1, 0.8, 0.2, 0.1, 0, 0, 0.1, 0.1, 0, 1,
                1, 1, 1, 1, 1, 0.9, 0.8, 0.3, 0.3]).reshape(2,10)
probit = np.array([np.inf, np.inf, 5.84162123, 4.15837877, 3.71844843,
                -np.inf, -np.inf, 3.71844843, 3.71844843, -np.inf,
                np.inf, np.inf, np.inf, np.inf, np.inf, np.inf,
                6.28155157, 5.84162123, 4.47559949, 4.47559949]).reshape(2,10)
log_qtys = np.zeros([len(qtys)])
tables = np.zeros([numTar, len(qtys), 4])
ht_collection = collections.OrderedDict()
for x, qty in enumerate(qtys): 
    log_qtys[x] = math.log10(qty)

for idx, tar in enumerate(targets):
    tables[idx,:,0] = qtys
    tables[idx,:,1] = log_qtys
    for i, val in enumerate(qtys):
        tables[idx,i,2] = prop[idx,i]
        tables[idx,i,3] = probit[idx,i]

# this is where makeplots is called. figure, subplots, and axes
# look beautiful at this point
fig, axs = makeplots(targets)

for i, tars in enumerate(targets):
    ht_collection[tars] = pd.DataFrame(tables[i,:,:], columns=["qty","log_qty","probability","probit"])
    ht_collection[tars].probit.replace([np.inf, -np.inf], np.nan, inplace=True)
    ht_collection[tars].dropna(inplace=True)

# this is where drawplots() is called and the figure/plots get uglified
    while True:
        if logans == 'y':
            r2, lod, eqn = drawplots(axs[i], ht_collection[tars].log_qty, ht_collection[tars].probit, logans, cbcolors[i], cbcolors[i+5])
            break
        elif logans == 'n':
            r2, lod, eqn = drawplots(axs[i], ht_collection[tars].qty, ht_collection[tars].probit, logans, cbcolors[i], cbcolors[i+5])
        raise ValueError(f"Error calling drawplots() - subplot {i+1} of {len(targets)+1}")
    if logconv == 'y': lod **=10

plt.ion()
#plt.savefig(f"{dt} LLoD Analysis at {tm}.png", format='png')
plt.show()
plt.pause(0.001)

我希望子圖保持正方形,因此如果一個子圖的 x 值在 [0,50] 范圍內,而另一個子圖的 x 值都在 [0,2] 范圍內,則 x 軸應重新縮放到相同的長度。 附件是一個“好”(但空白)圖和一個“壞”圖(目前被吐出)好圖! 糟糕的情節!

在代碼中關於第 82 行的drawplots()內部,嘗試使用ax.set_aspect('auto') (您當前已將其設置為ax.set_aspect('equal') )將其設置為'auto'生成您正在尋找的圖形: 在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM