簡體   English   中英

matplotlib 子圖沒有間距,限制圖形大小和tight_layout()

[英]matplotlib subplots with no spacing, restricted figure size and tight_layout()

我正在嘗試制作一個 plot ,它有兩個共享 x 軸的子圖,它們之間不應有空格。 我按照 matplotlib 庫中的創建相鄰子圖示例進行操作。 然而,我的 plot 需要有一個固定的尺寸,這讓一切變得復雜。 如果我只是按照示例添加一個固定大小的圖形大小,那么標簽就會被切斷。 如果我使用tight_layout包含標簽,那么這些圖是間隔的。 如何解決這個問題? 此外,標題應該更接近圖例。 任何幫助深表感謝!

示例程序,注釋掉tight_layout看看有什么不同。

import numpy as np                                                                                             
import matplotlib.pyplot as plt                                                                                
                                                                                                               
x_min = -2*np.pi                                                                                               
x_max = 2*np.pi                                                                                                
resolution = 101                                                                                               
x_vals = np.linspace(x_min, x_max, resolution)                                                                 
y_upper = np.cos(x_vals)                                                                                       
y_lower = -np.cos(x_vals)                                                                                      
data3 = np.sin(x_vals)                                                                                         
                                                                                                               
fig = plt.figure(figsize=(80/25.4, 80/25.4))  # figsize is needed for later usage of the plot                  
ax = fig.subplots(2, 1, sharex=True)                                                                           
fig.subplots_adjust(hspace=0)                                                                                  
                                                                                                               
ax[0].plot(x_vals, y_upper, label="data 1")                                                                    
ax[0].plot(x_vals, y_lower, label="data 2")                                                                    
                                                                                                               
ax[1].set_xlim([x_min,x_max])                                                                                  
ax[0].set_ylim([-1.6,1.6])                                                                                     
ax[1].set_ylim([-1.3,1.3])                                                                                     
                                                                                                               
ax[1].plot(x_vals, data3, ls='-', label="data 3", color='C2')                                                  
                                                                                                               
ax[1].set_xlabel("xaxis")                                                                                      
ax[0].set_ylabel("yaxis 1")                                                                                    
ax[1].set_ylabel("yaxis 2")                                                                                    
ax[0].legend(bbox_to_anchor=(0, 1.02, 1., 0.102), loc='lower left', ncol=2, mode="expand", borderaxespad=0)    
                                                                                                               
fig.suptitle("Title")                                                                                          
fig.tight_layout()  # comment this out to see the difference                                                   
# fig.savefig('figure.png')                                                                                    
plt.show()

您需要使用GridSpec而不是 subplots_adjust subplots_adjust() ,這樣, tight_layout()就會知道您想要零空間並保持這種狀態。

事實上,當您使用fig.subplots()時,您已經創建了一個GridSpec ,因此您只需要在gridspec_kw=中傳遞一些額外的參數

x_min = -2*np.pi                                                                                               
x_max = 2*np.pi                                                                                                
resolution = 101                                                                                               
x_vals = np.linspace(x_min, x_max, resolution)                                                                 
y_upper = np.cos(x_vals)                                                                                       
y_lower = -np.cos(x_vals)                                                                                      
data3 = np.sin(x_vals)                                                                                         
                                                                                                               
fig = plt.figure(figsize=(80/25.4, 80/25.4))  # figsize is needed for later usage of the plot             
#
# This is the line that changes. Instruct the gridspec to have zero vertical pad
#     
ax = fig.subplots(2, 1, sharex=True, gridspec_kw=dict(hspace=0))                                                                           
                                                                                          
ax[0].plot(x_vals, y_upper, label="data 1")                                                                    
ax[0].plot(x_vals, y_lower, label="data 2")                                                                    
                                                                                                               
ax[1].set_xlim([x_min,x_max])                                                                                  
ax[0].set_ylim([-1.6,1.6])                                                                                     
ax[1].set_ylim([-1.3,1.3])                                                                                     
                                                                                                               
ax[1].plot(x_vals, data3, ls='-', label="data 3", color='C2')                                                  
                                                                                                               
ax[1].set_xlabel("xaxis")                                                                                      
ax[0].set_ylabel("yaxis 1")                                                                                    
ax[1].set_ylabel("yaxis 2")                                                                                    
ax[0].legend(bbox_to_anchor=(0, 1.02, 1., 0.102), loc='lower left', ncol=2, mode="expand", borderaxespad=0)    
                                                                                                               
fig.suptitle("Title")                                                                                          
fig.tight_layout()  # Now tight_layout does not add padding between axes
# fig.savefig('figure.png')                                                                                    
plt.show()

在此處輸入圖像描述

使用子圖獲得精確結果可能會令人沮喪 - 使用 gridspec ( https://matplotlib.org/3.3.3/tutorials/intermediate/gridspec.html ) 將提供更高的精度。

但是,考慮到您所在的位置,我認為您可以通過以下方式獲得所需的東西:

import matplotlib.pyplot as plt                                                                                
                                                                                                               
x_min = -2*np.pi                                                                                               
x_max = 2*np.pi                                                                                                
resolution = 101                                                                                               
x_vals = np.linspace(x_min, x_max, resolution)                                                                 
y_upper = np.cos(x_vals)                                                                                       
y_lower = -np.cos(x_vals)                                                                                      
data3 = np.sin(x_vals)                                                                                         
                                                                                                               
fig = plt.figure(figsize=(80/25.4, 80/25.4))  # figsize is needed for later usage of the plot                  
ax = fig.subplots(3, 1, sharex=True)                                                                           
fig.subplots_adjust(hspace=0)                                                                                  
ax[0].text(0,0.5,"Title", ha='center')
ax[0].axis("off")
ax[1].plot(x_vals, y_upper, label="data 1")                                                                    
ax[1].plot(x_vals, y_lower, label="data 2")                                                                    
                                                                                                               
ax[2].set_xlim([x_min,x_max])                                                                                  
ax[1].set_ylim([-1.6,1.6])                                                                                     
ax[2].set_ylim([-1.3,1.3])                                                                                     
                                                                                                               
ax[2].plot(x_vals, data3, ls='-', label="data 3", color='C2')                                                  
                                                                                                               
ax[2].set_xlabel("xaxis")                                                                                      
ax[1].set_ylabel("yaxis 1")                                                                                    
ax[2].set_ylabel("yaxis 2")                                                                                    
ax[1].legend(bbox_to_anchor=(0, 1.02, 1., 0.102), loc='lower left', ncol=2, mode="expand", borderaxespad=0)    

#fig.tight_layout()  # comment this out to see the difference                                                   
# fig.savefig('figure.png')                                                                                    
plt.show()

在此處輸入圖像描述

當然, gridspec是正確的方法,如果你處於腳本編寫的早期階段,你應該適應這個. 但是,如果你想要一個簡單的修復,你也可以移動fig.subplots_adjust()

#...
fig.suptitle("Title")                                                                                          
fig.tight_layout()    
fig.subplots_adjust(hspace=0)                                            
# fig.savefig('figure.png')                                                                                    
plt.show()

保存的圖像:
在此處輸入圖像描述

暫無
暫無

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

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