【问题标题】:Matplotlib, eliminate space between subplotsMatplotlib,消除子图之间的空间
【发布时间】:2023-02-09 02:08:36
【问题描述】:

我正在寻找一种方法来消除子图之间的垂直空间。我尝试使用 fig.subplots_adjust(hspace=0),但这似乎没有用。 任何人都知道这样做的方法吗?

我将在下面添加我正在使用的代码(即使它可能有点长),但如果你想自己尝试运行它,这里有一个指向我的 github 的链接,其中包含 jupyter 代码和我正在使用的文件

https://github.com/FrancescoAzzollini/Langmuir-Waves-Analysis

先谢谢您的帮助。

import numpy as np
import datetime as dt
import matplotlib.pyplot as plt
from matplotlib import colors
import pandas as pd
import matplotlib.dates as mdates
from matplotlib.ticker import MaxNLocator
from matplotlib.colors import LogNorm
from matplotlib.pyplot import cm

event_start_time = dt.datetime(2002,4,25,5,56,6) # start time of the event
f2_header = 46 # 6 eV to 1113 eV 
f3_header = 51 # 200 eV to 27 keV 
f1_header = 72 # 27 keV up 
spec_header = 43

date_for_path = '25-04-2002'
path = 'Langmuir waves analysis/' + date_for_path + '/'
spec_name = 'WI_H1_WAV_23030.csv'
f2_name = 'WI_ELSP_3DP_23030.csv' # ELSP
f3_name = 'WI_EHSP_3DP_23030.csv' # EHSP
f1_name = 'WI_SFSP_3DP_23030.csv' # SFSP


def arrival_time(E):
    m = 9.1e-31
    v = np.sqrt(3.2e-16 * E/m)
    dist = 215*7e8
    t = dist/v
    return event_start_time + dt.timedelta(0,t) 


df_spec = pd.read_csv(path + spec_name, header=spec_header, skipfooter=3)
df_spec['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'] = pd.to_datetime(df_spec['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'], format = '%Y-%m-%dT%H:%M:%S.%fZ')

dates_list = df_spec['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'].to_list()
x_lims_ = [dates_list[0].timestamp(), dates_list[-1].timestamp()]
x_lims = list(map(dt.datetime.fromtimestamp, x_lims_))
x_lims = mdates.date2num(x_lims)

y_lims0 = np.linspace(1075, 13825, 100)
y_lims1 = np.linspace(20, 1040, 100)
y_lims2 = np.linspace(4, 245, 100)

@plt.FuncFormatter
def fake_log(x, pos):
    'The two args are the value and tick position'
    return round(10**x) #r'$10^{%.2f}$' % (x)

df_spec = df_spec.set_index('EPOCH_yyyy-mm-ddThh:mm:ss.sssZ')
df_spec = df_spec[df_spec.columns[::-1]].T

df_spec0 = df_spec.iloc[353:-1, :]
df_spec1 = df_spec.iloc[95:353, :]
df_spec2 = df_spec.iloc[0:95, :]

date_format = mdates.DateFormatter('%H:%M:%S')
locator = mdates.HourLocator([4, 5, 6, 7, 8, 9])

fig, ax = plt.subplots(6, 1, figsize=(15,20), layout='compressed')

col_posit = -0.1
flare_time = dt.datetime.fromtimestamp(event_start_time.timestamp() + 3600)
flare_time = mdates.date2num(flare_time)


for a in ax:
    a.set_anchor('W')

for a in ax:
    a.patch.set_facecolor('black')

im = ax[0].imshow(df_spec0, norm=colors.LogNorm(), cmap=cm.inferno,
                  extent = [x_lims[0], x_lims[1],  np.log10(y_lims0[0]), np.log10(y_lims0[-1])], aspect='auto')
fig.colorbar(im, ax=ax[0], pad=col_posit)

ax[0].xaxis.set(major_formatter=date_format)
ax[0].tick_params(bottom = False)
ax[0].set_xticks([])
ax[0].yaxis.set_major_formatter(fake_log)
ax[0].yaxis.set_major_locator(MaxNLocator(5)) 
ax[0].set_yticks(np.log10(np.array([2000, 5000, 10000])))


im = ax[1].imshow(df_spec1, norm=colors.LogNorm(), cmap=cm.inferno,
                  extent = [x_lims[0], x_lims[1],  np.log10(y_lims1[0]), np.log10(y_lims1[-1])], aspect='auto')
fig.colorbar(im, ax=ax[1], pad=col_posit)

ax[1].xaxis.set(major_formatter=date_format)
ax[1].tick_params(bottom = False)
ax[1].set_xticks([])
ax[1].yaxis.set_major_formatter(fake_log)
ax[1].yaxis.set_major_locator(MaxNLocator(5)) 
ax[1].set_yticks(np.log10(np.array([20, 50, 100, 200, 500, 1000])))


im = ax[2].imshow(df_spec2, norm=colors.LogNorm(), cmap=cm.inferno, 
                  extent = [x_lims[0], x_lims[1],  np.log10(y_lims2[0]), np.log10(y_lims2[-1])], aspect='auto')
fig.colorbar(im, ax=ax[2], pad=col_posit)

ax[2].xaxis.set(major_formatter=date_format)
ax[2].tick_params(bottom = False)
ax[2].set_xticks([])
ax[2].yaxis.set_major_formatter(fake_log)
ax[2].yaxis.set_major_locator(MaxNLocator(5)) 
ax[2].set_yticks(np.log10(np.array([10, 20, 50, 100, 200])))

#second set of images

df1 = pd.read_csv(path + f1_name, header=f1_header, skipfooter=3)
df1['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'] = pd.to_datetime(df1['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'], format = '%Y-%m-%dT%H:%M:%S.%fZ')

df2 = pd.read_csv(path + f2_name, header=f2_header, skipfooter=3)
df2['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'] = pd.to_datetime(df2['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'], format = '%Y-%m-%dT%H:%M:%S.%fZ')

df3 = pd.read_csv(path + f3_name, header=f3_header, skipfooter=3)
df3['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'] = pd.to_datetime(df3['EPOCH_yyyy-mm-ddThh:mm:ss.sssZ'], format = '%Y-%m-%dT%H:%M:%S.%fZ')


i1, i2, i3 = 1, 1, 1
energies1 = [27, 40, 66, 108, 181, 310, 517]
energies2 = list(reversed(list(np.array([6, 7, 9, 13, 18, 27, 41, 65, 103, 164, 264, 426, 689, 1113])*1e-3)))
energies3 = list(reversed([0.137, 0.2, 0.29, 0.43, 0.64, 0.92, 1.34, 1.95, 2.85, 4.16, 6.08, 6.87, 12.97, 18.9, 27]))

#fig, ax = plt.subplots(3, 1, figsize=(10,10))
while i1 < 8 :
    ax[5].plot(df1.iloc[:, 0], df1.iloc[:, i1], c=cm.rainbow([50*i1]))
    ax[5].vlines(arrival_time(energies1[i1-1]), 0,0.3, color=cm.rainbow([50*i1]), label = str(energies1[i1-1]) + ' keV')
    ax[5].set_xlim(df3.iloc[0, 0], df3.iloc[-1, 0])
    ax[5].set_yscale("log")
    plt.gcf().autofmt_xdate()
    i1 += 1

while i2 < 15 :
    ax[3].plot(df2.iloc[:, 0], df2.iloc[:, i2], c=cm.rainbow([20*i2]), label = str(round(energies2[i2-1]*1e3)) + ' eV')
    ax[3].vlines(arrival_time(energies2[i2-1]), 0,4e8, color=cm.rainbow([20*i2]))
    ax[3].set_xlim(df3.iloc[0, 0], df3.iloc[-1, 0])
    ax[3].set_yscale("log")
    i2 += 1

while i3 < 15 :
    ax[4].plot(df3.iloc[:, 0], df3.iloc[:, i3], c=cm.rainbow([20*i3]), label = str(round(energies3[i3-1]*1e3)) + ' eV')
    ax[4].vlines(arrival_time(energies3[i3-1]), 0,1e5, color=cm.rainbow([20*i3]))
    ax[4].set_xlim(df3.iloc[0, 0], df3.iloc[-1, 0])
    ax[4].set_yscale("log")
    i3 += 1

ax[0].vlines(flare_time, np.log10(y_lims0[0]), np.log10(y_lims0[-1]), 'r')
ax[1].vlines(flare_time, np.log10(y_lims1[0]), np.log10(y_lims1[-1]), 'r')
ax[2].vlines(flare_time, np.log10(y_lims2[0]), np.log10(y_lims2[-1]), 'r')
ax[4].set_ylim(None, 8e4)
ax[3].set_ylim(top=3e8)
ax[5].set_ylim(top=0.2)
ax[3].set_xticks([])
ax[4].set_xticks([])
ax[3].legend(loc='upper left', bbox_to_anchor=(1, 1),fontsize = 11, frameon=False)
ax[4].legend(loc='upper left', bbox_to_anchor=(1, 1),fontsize = 11, frameon=False)
ax[5].legend(loc='upper left', bbox_to_anchor=(1, 1),fontsize = 11, frameon=False)
ax[5].set_xlabel('UT', fontsize = 20)
ax[1].set_ylabel('Frequency [kHz]', fontsize = 20)
ax[4].set_ylabel('Eletrons $cm^{-2} ster^{-1} s^{-1} eV^{-1}$', fontsize = 20)
plt.rc('ytick', labelsize=16)
plt.rc('xtick', labelsize=16)

#plt.show()
plt.savefig(path + "Spec_Plot_" + date_for_path, bbox_inches='tight')

【问题讨论】:

  • 你试过没有layout='compressed'吗?您能否将测试代码的大小大幅缩减为最小的可重现示例?现在有很多代码对这个问题不重要。
  • 我做到了,但不幸的是删除``` layout='compressed' ``` 重塑图像并且它们的 x 轴不再对齐。抱歉,代码太多,我会尝试举一个更简单的例子
  • 通常,plt.tight_layout() 用于消除子图之间的空间。

标签: python matplotlib subplot


【解决方案1】:

好消息,我今天早上设法解决了它。 我所做的是按照 JohanC 的建议去掉 layout='compressed',并使用 add_gridspecsubgridspec 创建嵌套的子图:两个外部子图,每个内部 3x2 子图。我使用 a.set_visible(False) 将右列的子图设置为不可见,然后操纵它们的相对宽度以使 x 轴对齐并获得所需的结果。

我用新的工作代码更新了我的 github 存储库。 感谢大家的帮助:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 2021-11-19
    • 1970-01-01
    • 2017-07-29
    • 2013-12-25
    • 1970-01-01
    相关资源
    最近更新 更多