使用Dash Plotly创建带滑块的3D交互图表出现空白问题求助
问题描述
尝试使用Dash Plotly创建关联三个滑块的3D交互图表,但运行代码后仅显示带有滑块的空白2D图表,求排查代码错误。
数据
| A | C | B |
|---|---|---|
| 191 | 11870402.57 | 150927.156 |
| 194 | 11534176.96 | 150926.613 |
| 200 | 8791715.569 | 150309.893 |
| 219 | 9058784.693 | 130344.409 |
| 193 | 11710374.76 | 150993.204 |
| 230 | 8966576.793 | 121803.204 |
| 196 | 11563137.82 | 147352.525 |
| 197 | 11559778.19 | 147360.662 |
| 232 | 8145250.015 | 134850.363 |
| 230 | 8960357.94 | 122119.87 |
| 241 | 8343604.908 | 118177.929 |
应用布局代码
from dash import Dash, dcc, html, Input, Output import plotly.express as px import pandas as pd app = Dash(name) app.layout = html.Div([ html.H4('Illustrations'), dcc.Graph(id='graph_scatter'), html.P('A:'), dcc.Slider( id='3d-scatter-plot-x-range-slider', min=df['A'].min(), max=df['A'].max(), value=df['A'].max()), html.P('B:'), dcc.Slider( id='3d-scatter-plot-y-range-slider', min=df['B'].min(), max=df['B'].max(), value=df['B'].max()), html.P('C:'), dcc.Slider( id='3d-scatter-plot-z-range-slider', min=df['C'].min(), max=df['C'].max(), value=df['C'].max()) ])
回调代码
@app.callback( Output('graph', 'figure'), [Input('3d-scatter-plot-x-range-slider', 'value'), Input('3d-scatter-plot-y-range-slider', 'value'), Input('3d-scatter-plot-z-range-slider', 'value')]) def update_bar_chart(slider_range_x, slider_range_y, slider_range_z): df = pd.read_csv('ABC.csv') # replace with your own data source low_x, high_x = slider_range_x low_y, high_y = slider_range_y low_z, high_z = slider_range_z mask = (df.A > low_x) & (df.A < high_x) & ( df.B > low_y) & (df.B < high_y) & ( df.C > low_z) & (df.C < high_z) fig = px.scatter_3d(mask, x='A', z='C', y='B') return fig if __name__ == '__main__': app.run_server(debug=False)
错误排查与修复方案
直接修正以下几个核心问题就能解决:
Graph组件ID不匹配:布局里的Graph id是
graph_scatter,但回调Output写的是graph,导致图表无法接收更新后的figure。把回调里的Output('graph', 'figure')改成Output('graph_scatter', 'figure')。滑块类型错误:你需要的是范围选择滑块,当前用的
dcc.Slider只能返回单个值,无法拆成low/high两个变量。换成dcc.RangeSlider,同时设置初始范围值,比如value=[df['A'].min(), df['A'].max()]。数据加载时机错误:布局代码里直接用了
df['A'].min(),但此时还没加载数据,启动会报错。先加载数据再定义布局:df = pd.read_csv('ABC.csv') # 提前加载数据 app = Dash(__name__) # 注意这里参数是__name__,不是name app.layout = html.Div([...]) # 再定义布局Mask使用错误:
px.scatter_3d需要传入筛选后的DataFrame,直接传布尔数组mask会导致数据异常。改成px.scatter_3d(df[mask], ...)。冗余数据加载:回调里每次都重新读取CSV,效率低,把数据加载放在回调外面即可。
修复后完整代码
from dash import Dash, dcc, html, Input, Output import plotly.express as px import pandas as pd # 提前加载数据 df = pd.read_csv('ABC.csv') app = Dash(__name__) app.layout = html.Div([ html.H4('Illustrations'), dcc.Graph(id='graph_scatter'), html.P('A:'), dcc.RangeSlider( id='3d-scatter-plot-x-range-slider', min=df['A'].min(), max=df['A'].max(), value=[df['A'].min(), df['A'].max()]), html.P('B:'), dcc.RangeSlider( id='3d-scatter-plot-y-range-slider', min=df['B'].min(), max=df['B'].max(), value=[df['B'].min(), df['B'].max()]), html.P('C:'), dcc.RangeSlider( id='3d-scatter-plot-z-range-slider', min=df['C'].min(), max=df['C'].max(), value=[df['C'].min(), df['C'].max()]) ]) @app.callback( Output('graph_scatter', 'figure'), [Input('3d-scatter-plot-x-range-slider', 'value'), Input('3d-scatter-plot-y-range-slider', 'value'), Input('3d-scatter-plot-z-range-slider', 'value')]) def update_3d_scatter(slider_range_x, slider_range_y, slider_range_z): low_x, high_x = slider_range_x low_y, high_y = slider_range_y low_z, high_z = slider_range_z mask = (df.A > low_x) & (df.A < high_x) & \ (df.B > low_y) & (df.B < high_y) & \ (df.C > low_z) & (df.C < high_z) fig = px.scatter_3d(df[mask], x='A', z='C', y='B') return fig if __name__ == '__main__': app.run_server(debug=False)
内容的提问来源于stack exchange,提问作者Jagriti Tiwari
相关产品推荐
相关产品推荐

