Matplotlib如何在imshow和plot之间共享x轴

3
我试图在共享x轴的两个imshow和一个plot上面绘制它们。该图的布局是使用gridspec设置的。 这是一个最小工作示例:
    import matplotlib as mpl
    from matplotlib import pyplot as plt
    import numpy as np
    fig = plt.figure(figsize=(10,8))
    gs = fig.add_gridspec(3,2,width_ratios=(1,2),height_ratios=(1,2,2), left=0.1,right=0.9,bottom=0.1,top=0.99, wspace=0.1, hspace=0.1)
    ax=fig.add_subplot(gs[2,1])
    ax2=fig.add_subplot(gs[2,0], sharey=ax)
    ax3=fig.add_subplot(gs[1,0])
    ax4=fig.add_subplot(gs[1,1], sharex=ax, sharey=ax3)
    ax5=fig.add_subplot(gs[0,1], sharex=ax)
    
    dates = pd.date_range("2020-01-01","2020-01-10 23:00", freq="H")
    xs = mpl.dates.date2num(dates)
    ys = np.random.random(xs.size)
    N = 10
    arr = np.random.random((N, N))
    arr2 = np.random.random((N, N))
    
    norm=mpl.colors.Normalize(0, arr.max()) # change the min to stretch the color spectrum
    pcm = ax.imshow(arr, extent=[xs[0],xs[-1],10,0],norm=norm,aspect='auto')
    cax = fig.colorbar(pcm, ax=ax, extend='max') # , location='left'
    ax.set_xlabel('date')
    cax.set_label('fraction [-]')
    # ax.xaxis_date()
    myFmt = mpl.dates.DateFormatter('%d.%m')
    ax.xaxis.set_major_formatter(myFmt)
    
    norm=mpl.colors.Normalize(0, arr2.max()) # change the min to stretch the color spectrum
    pcm = ax4.imshow(arr2, extent=[xs[0],xs[-1],1,0],norm=norm,aspect='auto')
    cax4 = fig.colorbar(pcm, ax=ax4, extend='max')
    cax4.set_label('fraction [-]')
    
    ax5.plot(xs,ys)

    con1 = ConnectionPatch(xyA=(ax2.get_xlim()[0],1), xyB=(ax2.get_xlim()[0],1), 
                       coordsA="data", coordsB="data", connectionstyle=mpl.patches.ConnectionStyle("Bar", fraction=-0.05),
                       axesA=ax2, axesB=ax3, arrowstyle="-", color='r')
    
    con2 = ConnectionPatch(xyA=(ax2.get_xlim()[0],0), xyB=(ax2.get_xlim()[0],0), 
                       coordsA="data", coordsB="data", connectionstyle=mpl.patches.ConnectionStyle("Bar", fraction=-0.02),
                       axesA=ax2, axesB=ax3, arrowstyle="-", color='r')
    
    fig.add_artist(con1)
    fig.add_artist(con2)

这个情节的最终结果如下: plot 尽管轴似乎是相互关联的(应用于所有轴的日期格式),但它们的范围不同。
注意:两个左轴不能共享相同的x轴。
编辑:添加了ConnectionPatch连接,但在使用constrained_layout时会出现断裂。

4
你可以采用三个子图列,而不是两个,明确为颜色条留出足够的空间 (width_ratios=(5,10,1))。然后你可以这样做 cax1 = fig.add_subplot(gs[1,2])fig.colorbar(...cax=cax1) 来将颜色条放在那里。 - JohanC
1个回答

5

Constrained_layout是专门为此情况设计的。它将与上面的gridspec解决方案一起工作,但更加符合惯用法:

import datetime as dt
import matplotlib as mpl
from matplotlib import pyplot as plt
import numpy as np
import pandas as pd

fig, axs = plt.subplot_mosaic([['.', 'plot'], ['empty1', 'imtop'],
                               ['empty2', 'imbottom']],
                              constrained_layout=True,
                              gridspec_kw={'width_ratios':(1,2),'height_ratios':(1,2,2)})

axs['imtop'].sharex(axs['imbottom'])
axs['plot'].sharex(axs['imtop'])

dates = pd.date_range("2020-01-01","2020-01-10 23:00", freq="H")
xs = mpl.dates.date2num(dates)
ys = np.random.random(xs.size)
N = 10
arr = np.random.random((N, N))
arr2 = np.random.random((N, N))

norm=mpl.colors.Normalize(0, arr.max()) # change the min to stretch the color spectrum
pcm = axs['imtop'].imshow(arr, extent=[xs[0],xs[-1],10,0],norm=norm,aspect='auto')
cax = fig.colorbar(pcm, ax=axs['imtop'], extend='max')

norm=mpl.colors.Normalize(0, arr2.max()) # change the min to stretch the color spectrum
pcm = axs['imbottom'].imshow(arr2, extent=[xs[0],xs[-1],1,0],norm=norm,aspect='auto')
cax4 = fig.colorbar(pcm, ax=axs['imbottom'], extend='max')

axs['plot'].plot(xs,ys)

enter image description here


我在测试之前就接受了。实际上,这个答案存在一个问题。在我的MWE中,我跳过了这一点,但原始图形在不同的轴(empty1和empty2)之间有ConnectionPatch连接。由于某种原因,这似乎与constrained_layout不兼容。 - NicoH
将连接线从布局中移除(set_in_layout(False))或将其作为图形艺术家处理。 - Jody Klymak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接