Plotly:为同一条线添加主轴和次轴

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

我正在做一个学校项目。我创建了以下回调来更新图表。该图简单地绘制了:

  1. 一条显示变量 Wealth 值的线,
  2. 财富起始值处的水平线,
  3. 填充第一行和第二行之间的区域。

我想修改代码,在左侧的垂直轴上添加刻度,显示财富值与起始值之间的差异。因此,我不想添加第三行,我只想添加本质上显示利润的刻度线。我将在此代码片段下方展示我的尝试。

# Callbacks to update graphs based on the original code
@app.callback(
    Output('wealth-over-time', 'figure'),
    Input('wealth-time-range-slider', 'value'))
def update_wealth_over_time(selected_range):
    filtered_df = df[df['Day'].between(selected_range[0], selected_range[1])]
    # Create a new DataFrame for the fill area
    fill_area_df = pd.DataFrame({
        'Day': filtered_df['Day'],
        'Starting Wealth': starting_wealth,
        'Wealth ($)': filtered_df['Wealth ($)']
    })

    fig = go.Figure()
    
    # Add fill area between starting wealth and Wealth ($)
    fig.add_trace(go.Scatter(
        x=pd.concat([fill_area_df['Day'], fill_area_df['Day'][::-1]]),  # X-values concatenated with reverse for seamless fill
        y=pd.concat([fill_area_df['Starting Wealth'], fill_area_df['Wealth ($)'][::-1]]),  # Y-values for starting wealth and Wealth ($) with reverse for fill
        fill='toself',
        fillcolor='rgba(135, 206, 250, 0.5)',  # Light blue fill with transparency
        line=dict(color='rgba(255,255,255,0)'),  # Invisible line around the fill area
        showlegend=False,
        name='Fill Area',
    ))
    
    # Add Wealth ($) line on top of the fill area
    fig.add_trace(go.Scatter(
        x=filtered_df['Day'], 
        y=filtered_df['Wealth ($)'],
        mode='lines+markers',
        showlegend=False,
        name='Wealth ($)',
        line=dict(color='DeepSkyBlue'),
    ))

    # Add dashed horizontal line for starting wealth
    fig.add_shape(
        type='line',
        x0=filtered_df['Day'].min(),
        x1=filtered_df['Day'].max(),
        y0=starting_wealth,
        y1=starting_wealth,
        line=dict(color='Gray', dash='dash', width=2),
    )
    
    fig.update_layout(
        title={'text': "Wealth", 'font': {'color': 'black'}},
        plot_bgcolor='white',
        xaxis=dict(
            title='Day',
            color='black',
            showgrid=True,
            gridcolor='lightgrey',
            gridwidth=1,
            showline=True,
            linewidth=2,
            linecolor='black',
            mirror=True
        ),
        yaxis=dict(
            title='Wealth ($)',
            color='black',
            showgrid=True,
            gridcolor='lightgrey',
            gridwidth=1,
            showline=True,
            linewidth=2,
            linecolor='black',
            mirror=True
        ),
        xaxis_range=[filtered_df['Day'].min(), filtered_df['Day'].max()]
    )
    fig.add_shape(
        go.layout.Shape(
            type="line",
            x0=min(filtered_df['Day']),
            y0=starting_wealth,
            x1=max(filtered_df['Day']),
            y1=starting_wealth,
            line=dict(
                color="black",
                width=2,
                dash="dash",
            ),
        )
    )
    return fig

这会生成以下图像:

我尝试按照此处所示的步骤进行此修改。特别是,我做了以下更改:

  1. from plotly.subplots import make_subplots

    
    

  2. Changed fig = go.Figure()

    fig = make_subplots(specs=[[{"secondary_y": True}]])
    
    

  3. 添加

    secondary_y=True

    如下:

# Add Wealth ($) line on top of the fill area fig.add_trace(go.Scatter( x=filtered_df['Day'], y=filtered_df['Wealth ($)'], mode='lines+markers', showlegend=False, name='Wealth ($)', line=dict(color='DeepSkyBlue'), ), secondary_y=True,)
但是,当我运行代码时,

1)蓝色区域不再正确对齐

2)我不知道如何显示正确的刻度线(左侧刻度线与财富起始值的差异)。

我真的很感激一些帮助。

python plotly plotly-dash
1个回答
0
投票
有两件事:

  1. 填充和图形不对齐的问题是因为你给了线它自己的轴(secondary_y = True)。如果不指定,系统会自动为其分配一个范围。您可以通过手动设置两个 Y 轴的范围来解决此问题,或者获取填充的自动范围并将其分配给第二个 Y 轴。

  2. 解决您的原始问题的最简单的解决方案是添加一个带有 y 轴的空迹线,其定义为主轴范围减去起始值。

'

full_fig = fig.full_figure_for_development() org_yrange = full_fig.layout.yaxis.range sec_yrange = (0, org_yrange[1] - org_yrange[0]) fig.add_trace(go.Scatter(x=[],y=[],yaxis='y2')) fig.update_layout( yaxis2=dict( range=sec_yrange, side='right', overlaying='y', ), )
    
© www.soinside.com 2019 - 2024. All rights reserved.