matplotlib缩放y轴

matplotlib缩放y轴,matplotlib,plot,Matplotlib,Plot,我使用matplotlib在一个绘图中显示多个数据集。我希望次要数据有多个“外部”y轴,并且希望这些轴具有相同的范围,但缩放比主绘图轴的范围短 我正在使用twinx()创建附加的y轴,如中所述 MCV示例 这项工作的关键是操纵每个轴的Bbox。这个解决方案建立在 mpl=matplotlib,np=numpy,pd=pandas 创建主轴,ax 使用ax.Get_position()获取轴的坐标,然后使用Get_points()获取边界点axpos 使用创建辅助轴ax2 使用mpl.tran

我使用matplotlib在一个绘图中显示多个数据集。我希望次要数据有多个“外部”y轴,并且希望这些轴具有相同的范围,但缩放比主绘图轴的范围短

我正在使用twinx()创建附加的y轴,如中所述

MCV示例


这项工作的关键是操纵每个轴的Bbox。这个解决方案建立在

mpl=matplotlib,np=numpy,pd=pandas

  • 创建主轴,
    ax

  • 使用
    ax.Get_position()
    获取轴的坐标,然后使用
    Get_points()
    获取边界点
    axpos

  • 使用创建辅助轴ax2

  • 使用
    mpl.transforms.Bbox(np.copy(axpos))
    ax2
    ax2pos
    创建Bbox。确保创建原始Bbox点的副本,否则两者都将被修改

  • 缩放次边界框。这可以通过设置水平缩放的
    x1
    属性或垂直缩放的
    y1
    属性来实现。(例如,
    ax2pos.y1=0.5*ax2pos.y1

  • 使用设置次轴的边界框

  • 使用
    ax2关闭顶部(或右侧,用于水平缩放)。spines['top']。设置为可见(False)

  • 您可能还必须考虑:

    • 使用
      ax.patch.set_visible()
      切换每个轴,以避免在以前的层上绘制

    • 使用ax.set_zorder()调整轴的绘图顺序

    • 由于缩放,您可能必须调整保存图形时使用的边界框。这可以通过创建另一个Bbox并将其作为
      Bbox\u inches
      参数传递给来实现

    MCV解决方案

    完整代码解决方案

    更新

    由于matplotlib库中有更新,因此必须进行一些小的更改才能使其正常工作。执行
    ax.twinx()
    不再提供对第二个轴的控制,因此必须手动将其添加到图形中

    mpl=matplotlib,plt=matplotlib.pyplot,np=numpy,pd=pandas

  • 使用
    plt.subplot()创建主图形
    fig
    和轴
    ax

  • 如步骤2、4和5所示创建Bbox

  • 使用带有所需边界框的图add_axes()创建辅助轴ax2a

  • 通过成对创建右y轴
    ax2a
    ax2a.twinx()

  • 清理辅助轴

  • 您还需要考虑使用两个轴的主轴和次轴的X轴对齐。 MCV解决方案


    你能创建一个MCV吗?我已经添加了一个MCV。如果还有什么我能帮忙的,请告诉我。
    ax = day6Si.plot( 
      'time', 'pce_rolling'
    )
    
    dataPsc[ dataPsc.day == 5 ].plot( 
      'time', 'pce_rolling', ax = ax 
    )
    
    ax3 = ax.twinx()
    ax3.fill_between( 
      day6Si.time, 0, day6Si.temperature
    )
    
    rspine = ax3.spines[ 'right' ]
    rspine.set_position( ( 'axes', 1.15 ) )
    ax3.set_frame_on( True )
    ax3.patch.set_visible( False )
    ax3.set_ylim( bottom = 0 )
    
    
    ax2 = ax.twinx()
    ax2.fill_between( 
      day6Si.time, 0, day6Si.intensity
    )
    
    rspine = ax2.spines[ 'right' ]
    rspine.set_position( ( 'axes', 1.05 ) )
    ax2.set_frame_on( True )
    ax2.patch.set_visible( False )
    ax2.set_ylim( bottom = 0 )
    
    td = np.linspace( 0, np.pi, 101 )
    df = pd.DataFrame( data = {
      'main': np.sin( td ),
      'secondary': 10 * np.sin( td )
    } )
    
    ax = df.plot( df.index.values, 'main' )
    
    ax2 = ax.twinx()
    ax2.fill_between( 
      df.index.values, 0, df.secondary, 
      facecolor = '#a05050', 
      label = 'Secondary'
    )
    
    rspine = ax2.spines[ 'right' ]
    rspine.set_position( ( 'axes', 1.05 ) )
    ax2.set_frame_on( True )
    ax2.patch.set_visible( False )
    ax2.set_ylim( bottom = 0 )
    ax2.set_ylabel( 'Secondary' )
    
    ax.set_ylim( 0, 1 )
    ax.legend( [ 'Main', 'Secondary' ] )
    
    td = np.linspace( 0, np.pi, 101 )
    df = pd.DataFrame( data = {
      'main': np.sin( td ),
      'secondary': 10 * np.sin( td )
    } )
    
    ax = df.plot( df.index.values, 'main' )
    axpos = ax.get_position()
    
    ax2 = ax.twinx()
    ax2pos = mpl.transforms.Bbox( np.copy( axpos.get_points() ) ) # clone bounding box
    ax2pos.y1 = ax2pos.y1 * 0.5 # scale y axis
    ax2.set_position( ax2pos ) # set bounding box
    
    ax2.fill_between( 
      df.index.values, 0, df.secondary, 
      facecolor = '#a05050', 
      label = 'Secondary'
    )
    
    ax2.spines[ 'right' ].set_position( ( 'axes', 1.05 ) )
    ax2.spines[ 'top' ].set_visible( False )
    ax2.set_frame_on( True )
    ax2.patch.set_visible( False )
    ax2.set_ylim( bottom = 0 )
    ax2.set_ylabel( 'Secondary' )
    
    ax.set_ylim( 0, 1 )
    ax.legend( [ 'Main', 'Secondary' ] )
    
    ax = day6Si.plot( 
       'time', 'pce_rolling', kind = 'line', label = 'Si',
        zorder = 40
    )
    
    dataPsc[ dataPsc.day == 5 ].plot( 
        'time', 'pce_rolling', kind = 'line', label = 'PSC',
        zorder = 30, ax = ax 
    )
    
    axpos = ax.get_position()
    ax.set_zorder( 30 )
    ax.patch.set_visible( False )
    
    ax.set_xlim( 124.5, 141.5 )
    ax.set_ylim( 10, 20 )
    ax.set_ylabel( 'PCE (%)' )
    ax.set_xlabel( 'Time' )
    ax.set_xticklabels( [ '4', '6', '8', '10', '12', '14', '16', '18', '20' ] )
    ax.legend( loc = 'upper right', bbox_to_anchor = ( 1, 1 ) )
    
    # temperature
    ax3 = ax.twinx()
    ax3.fill_between( 
        day6Si.time, 0, day6Si.temperature, 
        facecolor = '#f0c5b5',
        label = 'Temperature (Rel)'
    )
    
    ax3pos = mpl.transforms.Bbox( np.copy( axpos.get_points() ) ) # clone bounding box
    ax3pos.y1 = ax3pos.y1 * 0.5 # scale y axis
    ax3.set_position( ax3pos ) # set bounding box
    
    ax3.set_zorder( 10 )
    ax3.spines[ 'right' ].set_position( ( 'axes', 1.025 ) ) # shift y axis
    ax3.set_frame_on( True )
    ax3.spines[ 'top' ].set_visible( False ) # remove top frame line
    ax3.patch.set_visible( True )
    ax3.set_ylim( bottom = 0, top = 60 )
    ax3.set_ylabel( 'Temperature (C)' )
    
    # intensity
    ax2 = ax.twinx()
    ax2.fill_between( 
        day6Si.time, 0, day6Si.intensity, 
        facecolor = '#dddd99',
        label = 'Intensity (Rel)'
    )
    
    ax2pos = mpl.transforms.Bbox( np.copy( axpos.get_points() ) ) # clone bounding box
    ax2pos.y1 = ax2pos.y1 * 0.33 # scale y axis
    ax2.set_position( ax2pos ) # set bounding box
    
    ax2.set_zorder( 20 )
    ax2.spines[ 'right' ].set_position( ( 'axes', 1.125 ) ) # shift y asix
    ax2.set_frame_on( True )
    ax2.spines[ 'top' ].set_visible( False ) # remove top frame
    ax2.patch.set_visible( False )
    ax2.set_ylim( bottom = 0, top = 1 )
    ax2.set_ylabel( 'Intensity (suns)' )
    
    savebox = mpl.transforms.Bbox( [ [ 0, 0 ], [ 10* 1.15, 8 ] ] ) # bounding box in inches for saving
    plt.gcf().savefig( figloc + '/day6.svg', format = 'svg', bbox_inches = savebox )
    
    td = np.linspace( 0, np.pi, 101 )
    df = pd.DataFrame( data = {
      'main': np.sin( td ),
      'secondary': 10 * np.sin( td )
    } )
    
    fig, ax = plt.subplots()
    
    df.plot( df.index.values, 'main', ax = ax )
    axpos = ax.get_position()
    
    ax2pos = mpl.transforms.Bbox( np.copy( axpos.get_points() ) )
    ax2pos.y1 = ax2pos.y1 * 0.5 # scale y axis
    
    ax2a = fig.add_axes( ax2pos ) # create secondary axes
    ax2 = ax2a.twinx() # create right y-axis
    
    ax2.fill_between( 
      df.index.values, 0, df.secondary, 
      facecolor = '#a05050', 
      label = 'Secondary'
    )
    
    ax2.spines[ 'right' ].set_position( ( 'axes', 1.05 ) )
    ax2.spines[ 'top' ].set_visible( False )
    ax2.set_frame_on( True )
    ax2.patch.set_visible( False )
    ax2.set_ylim( bottom = 0 )
    ax2.set_ylabel( 'Secondary' )
    
    # clean up secondary axes tick marks and labels
    ax2a.tick_params( left = False, bottom = False )
    ax2.tick_params( left = False, bottom = False )
    ax2a.set_xticklabels( [] )
    ax2a.set_yticklabels( [] )
    
    ax.set_ylim( 0, 1 )
    ax.legend( [ 'Main', 'Secondary' ] )