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
相关产品推荐
相关产品推荐

