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

Plotly scatter_mapbox+Dash筛选时气泡大小及颜色不更新问题

问题原因分析

出现这个问题的核心原因是Plotly Express默认会复用全局的视觉属性尺度(比如颜色映射、大小缩放范围),即使传入筛选后的数据集,它可能仍保留初始全量数据的尺度,导致气泡大小和颜色看起来没有随筛选结果更新。另外,固定的size_max参数也会让不同年份的气泡大小对比失去意义——比如当某年份最大count值远小于其他年份时,气泡会显得过小,看起来像是没变化。

解决方案

下面提供两种可行的修复方案:

方案一:优化Plotly Express调用,强制基于当前数据计算尺度

在创建散点地图时,明确指定size_range基于当前筛选后的数据,并确保颜色映射动态适配当前的分类:

@app.callback(
    Output('graph-with-slider', 'figure'),
    Input('year-slider', 'value'))
def update_figure(selected_year):
    filtered_df = dfAgg[dfAgg.year == selected_year]
    
    # 处理counts全相同的边界情况
    min_count = filtered_df['counts'].min()
    max_count = filtered_df['counts'].max()
    size_range = [10, 70] if min_count == max_count else [min_count, max_count]
    
    fig = px.scatter_mapbox(
        filtered_df, 
        lat="y", 
        lon="x",
        color='category', 
        size='counts',
        hover_name="category", 
        size_max=70,
        size_range=size_range,  # 强制基于当前数据的counts范围缩放
        color_discrete_sequence=px.colors.qualitative.D3  # 用动态颜色序列避免缓存
    )
    fig.update_layout(mapbox_style="open-street-map")
    
    # 确保图例只显示当前年份存在的分类
    fig.for_each_trace(lambda t: t.update(visible=True) if t.name in filtered_df['category'].unique() else t.update(visible=False))
    
    return fig

方案二:改用Plotly Graph Objects手动构建(更可控)

如果Plotly Express的自动行为仍不符合预期,直接使用底层的Graph Objects手动创建trace,完全控制每个视觉属性:

import plotly.graph_objects as go

@app.callback(
    Output('graph-with-slider', 'figure'),
    Input('year-slider', 'value'))
def update_figure(selected_year):
    filtered_df = dfAgg[dfAgg.year == selected_year]
    
    # 为当前年份的分类分配颜色
    unique_cats = filtered_df['category'].unique()
    color_map = {cat: px.colors.qualitative.D3[i % len(px.colors.qualitative.D3)] for i, cat in enumerate(unique_cats)}
    
    fig = go.Figure()
    
    # 为每个分类单独添加trace
    for cat in unique_cats:
        cat_df = filtered_df[filtered_df['category'] == cat]
        fig.add_trace(go.Scattermapbox(
            lat=cat_df['y'],
            lon=cat_df['x'],
            mode='markers',
            marker=dict(
                size=cat_df['counts'] * 10,  # 手动调整大小缩放比例,可按需修改
                color=color_map[cat]
            ),
            name=cat,
            hovertext=cat_df['category']
        ))
    
    fig.update_layout(
        mapbox_style="open-street-map",
        zoom=12,
        showlegend=True
    )
    
    return fig
额外检查点
  • 验证筛选逻辑:在回调中添加print(filtered_df[['counts', 'category']]),确认每次滑块切换后的数据是否符合预期。
  • 检查数据类型:确保counts列是数值类型,category是字符串类型,无空值或异常值。

内容的提问来源于stack exchange,提问作者Giovanni Riccardi Lourenzatto

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 18:35:15