You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dash中仅选择Hexbin时添加专属图表参数?

问题

我开发了一个Dash回调函数,可切换展示Scatter、Heatmap、Hexbin等不同空间地图。当选中Hexbin选项时,希望添加nx_hexagon、min count等专属参数来修改图表,能否仅在选中Hexbin时启用这些参数?

解决方案

可以通过Dash的回调控制组件显隐来实现,核心是监听地图类型选择,动态切换Hexbin专属参数组件的可见性,同时在回调中接收参数并应用到图表生成:

  • 修正组件ID冲突:原代码中多个Slider共用my-sliderID,需给每个Slider分配唯一ID,例如opacity-slider、nx-hexagon-slider、min-count-slider。
  • 封装Hexbin专属控件:将nx_hexagon和min count的Slider包裹在一个单独的html.Div中,设置初始隐藏(style={'display': 'none'}),并给容器分配IDhexbin-controls。
  • 添加显隐控制回调:监听maps的输入值,当选中Hexbin时,设置容器样式为display: block,否则保持隐藏。
  • 更新图表生成逻辑:在图表回调中新增两个Slider的输入,生成Hexbin图表时将参数传入ff.create_hexbin_mapbox。

修改后的完整代码

import dash
from dash import dcc, html, Input, Output
import dash_bootstrap_components as dbc
import plotly.express as px
import plotly.graph_objs as go
import pandas as pd
import numpy as np
import plotly.figure_factory as ff

data = pd.DataFrame({
   'Cat': ['t','y','y','y','f','f','j','k','k','k','s','s','s','s'],
   'LAT': [5,6,4,5,4,7,8,9,5,6,18,17,15,16],
   'LON': [10,11,9,11,10,8,8,5,8,7,18,16,16,17],
   })

N = 30
data = pd.concat([data] * N, ignore_index=True)

data['Color'] = data['Cat'].map(dict(zip(data['Cat'].unique(), px.colors.qualitative.Plotly[:len(data['Cat'].unique())])))

Type_Category = data['Cat'].unique()
Type_cats = dict(zip(Type_Category, data['Color'].unique()))

external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.BOOTSTRAP]
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

filtering = html.Div([
    html.Div([
        html.Label('Cats', style={'paddingTop': '2rem', 'display': 'inline-block'}),
        dcc.Checklist(
            id='Cats',
            options=[{'label': cat, 'value': cat} for cat in Type_Category],
            value=list(Type_Category),
        ),

        html.Label('Type', style={'paddingTop': '2rem', 'display': 'inline-block'}),
        dcc.RadioItems(['Scatter', 'Heatmap', 'Hexbin'], 'Scatter', 
                       inline=True, id='maps'),

        html.Label('Opacity', style={'paddingTop': '2rem', 'display': 'inline-block'}),
        dcc.Slider(0, 1, 0.1,
                   value=0.5,
                   id='opacity-slider'),

        # Hexbin专属控件容器,初始隐藏
        html.Div(id='hexbin-controls', style={'display': 'none'}, children=[
            html.Label('nx_hexagon', style={'paddingTop': '2rem', 'display': 'inline-block'}),
            dcc.Slider(5, 40, 5,
                       value=20,
                       id='nx-hexagon-slider'),

            html.Label('min count', style={'paddingTop': '2rem', 'display': 'inline-block'}),
            dcc.Slider(0, 5, 1,
                       value=0,
                       id='min-count-slider')
        ]),
    ])
])

app.layout = dbc.Container([
    dbc.Row([
        dbc.Col([filtering], width=2),
        dbc.Col([dcc.Graph()]),
        dbc.Col([dcc.Graph(id='chart')])
    ])
], fluid=True)

df = data

# 控制Hexbin控件显隐的回调
@app.callback(
    Output('hexbin-controls', 'style'),
    Input('maps', 'value')
)
def toggle_hexbin_controls(map_type):
    if map_type == 'Hexbin':
        return {'display': 'block'}
    return {'display': 'none'}

# 图表生成回调
@app.callback(
    Output('chart', 'figure'),
    [Input('Cats', 'value'),
     Input('maps', 'value'),
     Input('opacity-slider', 'value'),
     Input('nx-hexagon-slider', 'value'),
     Input('min-count-slider', 'value')]
)
def update_chart(cats, map_type, opacity, nx_hex, min_count):
    dff = df[df['Cat'].isin(cats)]
    
    if map_type == 'Scatter':
        fig = px.scatter_mapbox(
            data_frame=dff,
            lat='LAT',
            lon='LON',
            color='Cat',
            color_discrete_map=Type_cats,
            zoom=3,
            mapbox_style='carto-positron',
        )
        fig.update_traces(opacity=opacity)

    elif map_type == 'Heatmap':
        [X, Y] = np.meshgrid(dff['LAT'], dff['LON'])
        Z = np.cos(X / 2) + np.sin(Y / 4)
        fig = go.Figure(data=go.Densitymapbox(
            lat=dff['LAT'],
            lon=dff['LON'],
            z=Z,
        ))
        fig.update_layout(mapbox_style="carto-positron")

    else:
        fig = ff.create_hexbin_mapbox(
            data_frame=dff, 
            lat="LAT", 
            lon="LON",
            nx_hexagon=nx_hex,
            min_count=min_count,
            opacity=opacity
        )
        fig.update_layout(mapbox_style="carto-positron")

    return fig

if __name__ == '__main__':
    app.run_server(debug=True, port=8051)

预期效果

选中Hexbin时的界面效果:
Hexbin预期效果

内容的提问来源于stack exchange,提问作者jonboy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 14:54:56