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

Plotly Dash:Mapbox散点图交互过滤后保留颜色与尺寸的方法

解决Plotly Dash Mapbox Scatter过滤后颜色/尺寸重映射问题

要阻止过滤后颜色和尺寸的重映射,核心是强制固定颜色和尺寸的原始映射范围,不让Plotly根据过滤后的数据自动调整。具体分两步实现:

1. 固定颜色映射范围

不要依赖Plotly自动生成颜色刻度,手动指定颜色轴的极值为原始数据的范围(比如你的0-10):

  • 在图表布局的coloraxis参数中设置cmin为原始最小值,cmax为原始最大值
  • 同时保持颜色条的刻度与原始范围一致,确保用户能直观对应数值和颜色

2. 固定尺寸映射范围

不能直接用Plotly的size参数让它自动缩放尺寸,需要提前基于原始数据极值计算每个点的固定尺寸:

  • 先定义尺寸的最小/最大值(比如最小5,最大20)
  • 按原始数据的比例计算每个点的尺寸:固定尺寸 = 最小尺寸 + (当前值/原始最大值) * (最大尺寸-最小尺寸)
  • 过滤数据后直接使用这个预计算的尺寸列,而非让Plotly重新映射

完整代码示例

import dash
from dash import dcc, html, Input, Output
import plotly.graph_objects as go
import pandas as pd

# 模拟原始数据(范围0-10)
df = pd.DataFrame({
    'lat': [40.7128, 34.0522, 41.8781, 29.7604, 39.7392],
    'lon': [-74.0060, -118.2437, -87.6298, -95.3698, -104.9903],
    'value': [1, 3, 5, 7, 9]
})

# 预计算固定尺寸:原始0对应size=5,10对应size=20
min_size = 5
max_size = 20
df['fixed_size'] = min_size + (df['value'] / 10) * (max_size - min_size)

app = dash.Dash(__name__)

app.layout = html.Div([
    dcc.RangeSlider(
        id='value-slider',
        min=0,
        max=10,
        step=0.5,
        value=[0, 10],
        marks={i: str(i) for i in range(0, 11)}
    ),
    dcc.Graph(id='mapbox-graph')
])

@app.callback(
    Output('mapbox-graph', 'figure'),
    Input('value-slider', 'value')
)
def update_graph(selected_range):
    # 过滤数据
    filtered_df = df[(df['value'] >= selected_range[0]) & (df['value'] <= selected_range[1])]
    
    # 创建图表
    fig = go.Figure(go.Scattermapbox(
        lat=filtered_df['lat'],
        lon=filtered_df['lon'],
        mode='markers',
        marker=dict(
            size=filtered_df['fixed_size'],  # 使用预计算的固定尺寸
            color=filtered_df['value'],
            coloraxis='coloraxis'  # 关联到固定的颜色轴设置
        )
    ))
    
    # 固定颜色轴范围
    fig.update_layout(
        mapbox_style='open-street-map',
        mapbox_zoom=3,
        mapbox_center={'lat': 37.0902, 'lon': -95.7129},
        coloraxis=dict(
            cmin=0,  # 原始最小值
            cmax=10,  # 原始最大值
            colorbar=dict(
                title='Value',
                tickvals=[0,2,5,8,10],
                ticktext=['0','2','5','8','10']
            )
        )
    )
    
    return fig

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

关键说明

  • 颜色映射:通过coloraxis的cmin和cmax强制锁定原始范围,过滤后剩余数据点的颜色会保持和原始数据一致的比例
  • 尺寸映射:预计算的fixed_size列确保每个点的尺寸只和原始数据值挂钩,过滤后不会被重新缩放

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 19:50:31