Plotly添加主次纵轴:修复填充错位与利润刻度显示问题
Dash双轴图表填充错位与利润刻度配置解决方案
问题核心原因
填充区域错位是因为相关trace绑定了不同的y轴,或者双轴的数值范围没有同步;利润刻度则需要基于「财富值-初始值」的线性关系来配置双轴映射。
具体解决步骤&代码示例
1. 计算利润数据
先从原始财富数据中算出利润(财富-初始值),不用单独绘制折线,仅用于配置左侧轴的范围:
initial_wealth = 1000 # 你的初始财富值 wealth_data = [1000, 1100, 950, 1200, 1300] # 你的财富时间序列数据 profit = [w - initial_wealth for w in wealth_data] x_data = [1, 2, 3, 4, 5] # 时间/索引轴数据
2. 统一绑定trace到同一y轴
所有涉及财富、初始值、填充的trace都绑定到右侧的「财富轴」(yaxis='y2'),避免填充跨轴错位:
import plotly.graph_objects as go from dash import Dash, Input, Output, dcc, html app = Dash(__name__) app.layout = html.Div([ dcc.Graph(id='wealth-profit-chart') ]) @app.callback( Output('wealth-profit-chart', 'figure'), # 这里可以替换为你的实际输入组件,比如下拉框、日期范围等 Input('wealth-profit-chart', 'id') # 示例用id触发初始化 ) def update_chart(_): fig = go.Figure() # 添加财富折线(绑定到y2轴) fig.add_trace(go.Scatter( x=x_data, y=wealth_data, name='当前财富', yaxis='y2', line=dict(color='#2c3e50') )) # 添加初始财富水平虚线(绑定到y2轴) fig.add_trace(go.Scatter( x=x_data, y=[initial_wealth]*len(x_data), name='初始财富', yaxis='y2', line=dict(color='#95a5a6', dash='dash') )) # 开启填充区域(基于同轴的两个trace) fig.update_traces(selector=dict(name='当前财富'), fill='tonexty', fillcolor='rgba(52, 152, 219, 0.3)') # 配置双轴 fig.update_layout( # 左侧利润轴 yaxis=dict( title='利润', tickmode='auto', # 自动生成刻度,也可以手动指定 # 手动指定刻度示例:tickvals=[-50, 0, 100, 200, 300], ticktext=['-50', '0', '100', '200', '300'] range=[min(profit), max(profit)], # 和利润数据范围对齐 side='left' ), # 右侧财富轴(覆盖在左侧轴上) yaxis2=dict( title='财富', overlaying='y', # 开启轴覆盖 range=[min(wealth_data), max(wealth_data)], # 和财富数据范围对齐 side='right' ), title='财富趋势与利润对比', showlegend=True, template='plotly_white' ) return fig if __name__ == '__main__': app.run_server(debug=True)
3. 关键注意事项
- 填充对齐核心:所有参与填充的trace必须绑定到同一个y轴,否则填充区域会基于不同轴的刻度计算,导致错位。
- 双轴同步:左侧利润轴的范围是
[min(profit), max(profit)],右侧财富轴的范围是[min(wealth_data), max(wealth_data)],两者的数值差正好是初始财富值,刻度会自动对齐(比如财富1000对应利润0,财富1200对应利润200)。 - 利润刻度自定义:如果需要手动设置利润刻度,直接修改
yaxis的tickvals和ticktext即可,比如tickvals=[-100, 0, 200]对应ticktext=['-100', '0', '200'],确保和财富轴的刻度一一对应(财富900→-100,1000→0,1200→200)。
内容的提问来源于stack exchange,提问作者NC520
相关产品推荐
相关产品推荐

