Plotly:在具有辅助 y 轴和固定范围的子图中数据和图形边界之间的填充

问题描述 投票:0回答:0

我正在寻找一个更好的解决方案来解决以下问题:如何让子图具有次要 y 轴、固定范围和主轴和次轴的重合零以及子图边界之间的填充?或者有没有办法在子图边界前显示数据?

我使用下面的代码创建如图所示的图形。

def plot_mpc_results(results, filename, output):
    if len(results) > 100:
        linemode = 'lines'
    else:
        linemode = 'lines+markers'

    fig = make_subplots(rows=4, cols=1, shared_xaxes = True,
                        specs = [[{"secondary_y": False}], [{"secondary_y": True}],  [{"secondary_y": False}], [{"secondary_y": False}]],
                        vertical_spacing = 0.01)
    if 'u_startup' in results.columns:
        fig.add_trace(go.Scatter(x=results.index, y=results['u_startup'],line_shape='hv', mode=linemode, name='u_startup', line_color='green', legendgroup='1'))
    fig.add_trace(go.Scatter(x=results.index, y=results['u_mode'], line_shape='hv', mode=linemode, name='u_mode', line_color='goldenrod', legendgroup='1'))
    fig.add_trace(go.Scatter(x=results.index, y=results['u_sp'],line_shape='hv', mode=linemode, name='u_sp', line_color='blue', legendgroup='1'))
    fig.update_yaxes(title_text='control', row=1, col=1, secondary_y=False)

    fig.add_trace(go.Scatter(x=results.index, y=results['P_pv'], mode='lines', name='P_pv', line_color='yellow', legendgroup='2'),row=2, col=1)
    fig.add_trace(go.Scatter(x=results.index, y=-results['P_el'], line_shape='hv', mode='lines', name='P_el', line_color='red', legendgroup='2'),row=2, col=1)
    fig.add_trace(go.Scatter(x=results.index, y=results['mdot_el'], line_shape='hv', mode='lines', name='mdot_el', line_color='blue', legendgroup='2'), row=2, col=1, secondary_y=True)
    fig.add_trace(go.Scatter(x=results.index, y=-results['m_exp'], line_shape='hv', mode='lines', name='m_exp', line_color='lightblue', legendgroup='2'), row=2, col=1, secondary_y=True)
    if 'mdot_magic' in results.columns:
        fig.add_trace(go.Scatter(x=results.index, y=results['mdot_magic'], line_shape='hv', mode='lines', name='mdot_magic', line_color='black', legendgroup='2'), row=2, col=1, secondary_y=True)
    fig.update_yaxes(title_text='power[kW]', row=2, col=1, secondary_y=False)
    fig.update_yaxes(title_text='H2flow [kg/h]', row=2, col=1, secondary_y=True)

    fig.add_trace(go.Scatter(x=results.index, y=results['m_st'], mode='lines', name='m_st', line_color='blue', legendgroup='3'), row=3, col=1)
    fig.update_yaxes(title_text='mass [kg]', row=3, col=1, secondary_y=False)

    fig.add_trace(go.Scatter(x=results.index, y=results['C_dayahead'], line_shape='hv', mode='lines',name='C_dayahead', line_color='black', legendgroup='4'), row=4, col=1)
    fig.update_yaxes(title_text='C_electricity [EUR/kWh]', row=4, col=1, secondary_y=False)

    fig.update_layout(yaxis_range=[0,1.1], yaxis2_range=[0,200], yaxis3_range=[0,3], yaxis4_range=[0,120])
    fig.update_layout(legend_tracegroupgap = 100)
    fig.update_xaxes(showspikes=True, spikecolor="black", spikethickness=1, spikemode="across")
    fig.update_layout(margin=dict(l=1, r=1, t=1, b=1))
    fig.update_layout(xaxis4=dict(autorange=True))
    fig.update_traces(xaxis="x4")
    #fig.update_layout(title=f'{filename}')
    if output == 'html':
        fig.write_html(f'{filename}.html', include_plotlyjs='cdn')  
    elif output == 'png':
        fig.write_image(f'{filename}.png', format='png', width=1600, height=900, scale=1)

#create sample dataframe
data = np.array([[0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [0.0, 0.0, 0.0, 0.0, 0.82, 0.82, 1.0, 0.82, 1.0, 0.82, 0.82, 0.82, 0.82, 0.82, 0.82, 0.82, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.82, 0.82, 0.82, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.56, 0.56, 0.56, 0.56, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.1, 3.92, 6.71, 21.6, 24.55, 26.12, 6.66, 0.23, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.58, 6.67, 12.03, 23.19, 37.83, 45.18, 27.07, 9.38, 0.51, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [-0.64, -0.64, -0.64, -1.76, -144.74, -144.74, -185.97, -144.74, -185.97, -144.74, -144.74, -144.74, -144.74, -144.74, -144.74, -144.74, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -1.76, -144.74, -144.74, -144.74, -0.64, -0.64, -0.64, -0.64, -0.64, -1.76, -95.25, -95.25, -95.25, -95.25, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64, -0.64], 
                [0.0, 0.0, 0.0, 0.0, 2.27, 2.27, 2.84, 2.27, 2.84, 2.27, 2.27, 2.27, 2.27, 2.27, 2.27, 2.27, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.27, 2.27, 2.27, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.49, 1.49, 1.49, 1.49, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 
                [10.0, 10.0, 10.0, 10.0, 10.0, 12.27, 14.53, 17.37, 19.64, 22.48, 24.75, 27.01, 29.28, 31.55, 33.81, 36.08, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 38.35, 40.62, 42.88, 45.15, 45.15, 45.15, 45.15, 45.15, 45.15, 45.15, 46.64, 48.13, 49.61, 51.1, 51.1, 51.1, 51.1, 51.1, 51.1, 51.1, 51.1, 51.1], 
                [0.05, 0.05, 0.05, 0.05, 0.04, 0.03, 0.03, 0.03, 0.03, 0.03, 0.04, 0.04, 0.04, 0.04, 0.04, 0.04, 0.05, 0.05, 0.05, 0.05, 0.06, 0.06, 0.05, 0.06, 0.06, 0.05, 0.05, 0.04, 0.04, 0.04, 0.05, 0.05, 0.05, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.06, 0.07, 0.07, 0.07, 0.07, 0.06, 0.06, 0.06]])
data = np.transpose(data)
df = pd.DataFrame(data=data, 
                  index=pd.DatetimeIndex(pd.date_range('2019-01-01 00:00:00', '2019-01-03 00:00:00', freq='H')), 
                  columns=['u_mode', 'u_sp', 'u_startup', 'P_pv', 'P_el', 'mdot_el', 'm_exp', 'mdot_magic', 'm_st', 'C_dayahead'])

# plot dataframe
plot_mpc_results(df, f'{ROOT}/data/stackoverflow', 'png')

我有一个固定的 y 轴范围,因为我必须在视觉上比较大量的图。在上面的两个子图中,数据与子图边界重合,这使得图形难以阅读且难看。我想在数据和子图边界之间有一些填充,就像自动调整范围一样,以使情节更漂亮。但是,我不需要自动调整范围,因为我需要固定的 y 轴范围。

我当然可以将固定的 y 轴范围设置为

fig.update_layout(yaxis_range=[-1,1.1], yaxis2_range=[-1,200], yaxis3_range=[-0.1,3], yaxis4_range=[-1,120])
。 然而,这会产生另一个问题:在从顶部开始的第二个子图中,也就是具有次要 y 轴的子图中,我希望零线重合,此解决方案不再发生这种情况。

当然,我可以计算出使初级和次级 y 轴的零点重合的 yaxis 范围:

yaxis2_range=[-2,200], yaxis3_range=[-0.03,3]
。这个技巧有效。

不过,有没有更漂亮的方案呢?如何使子图具有次要 y 轴、固定范围和主轴和次轴的重合零以及子图边界之间的填充?或者有没有办法在子图边界前显示数据?

python plotly plotly-python
© www.soinside.com 2019 - 2024. All rights reserved.