如何在Plotly Scattergeo美国地图中使用离散色阶
这确实是处理极端值可视化时的痛点——当少数城市的数值远远超出其他样本时,连续色阶会让大部分数据的颜色差异被“压缩”,根本看不清细节。离散色阶通过把数值划分为不同区间并分配独立颜色,能完美解决这个问题。下面我给你两种在Plotly中实现的实用方案,覆盖Express和Graph Objects两种常用方式:
方案1:用Plotly Express快速实现离散色阶
Express的语法更简洁,适合快速可视化。核心思路是先把连续的数值字段转换成离散的分类字段,再指定每个分类的颜色:
import plotly.express as px import pandas as pd # 模拟你的城市数据(替换成你的真实数据即可) city_data = pd.DataFrame({ "City": ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia"], "EventCount": [50000, 8200, 6700, 4300, 2900, 1800], "Lat": [40.7128, 34.0522, 41.8781, 29.7604, 33.4484, 39.9526], "Lon": [-74.0060, -118.2437, -87.6298, -95.3698, -112.0740, -75.1652] }) # 自定义离散区间和对应标签(根据你的数据分布调整) bins = [0, 2000, 5000, 20000, 50000] category_labels = ["0-2000", "2001-5000", "5001-20000", "20001-50000"] # 给数据添加分类列 city_data["EventCategory"] = pd.cut( city_data["EventCount"], bins=bins, labels=category_labels, include_lowest=True # 确保最小值被包含在第一个区间 ) # 自定义颜色映射(选你喜欢的配色) color_map = { "0-2000": "#e5f5f9", "2001-5000": "#99d8c9", "5001-20000": "#2ca25f", "20001-50000": "#006d2c" } # 绘制带离散色阶的地图(这里用散点地图,换成choropleth同理) fig = px.scatter_mapbox( city_data, lat="Lat", lon="Lon", color="EventCategory", color_discrete_map=color_map, size="EventCount", # 可选:用点的大小辅助区分数值高低 hover_name="City", hover_data={"EventCount": True, "EventCategory": False}, # 悬停时显示具体数值 mapbox_style="carto-positron", zoom=3 ) fig.update_layout(title="美国城市事件发生次数(离散色阶)") fig.show()
为什么这么做?
通过pd.cut把连续的EventCount转成离散分类后,每个区间对应固定颜色,纽约的50000会被分到最高档,而其他城市的区间颜色差异清晰可见,不会被极端值掩盖。如果你的数据分布不均匀,也可以用pd.qcut按分位数自动划分区间,比如pd.qcut(city_data["EventCount"], q=4, labels=category_labels),这样每个区间的样本量更均衡。
方案2:用Plotly Graph Objects实现更灵活的离散色阶
如果你需要更精细控制色条、标记样式等,Graph Objects是更好的选择。这里直接定义离散的颜色刻度映射:
import plotly.graph_objects as go import pandas as pd # 同样使用模拟数据 city_data = pd.DataFrame({ "City": ["New York", "Los Angeles", "Chicago", "Houston", "Phoenix", "Philadelphia"], "EventCount": [50000, 8200, 6700, 4300, 2900, 1800], "Lat": [40.7128, 34.0522, 41.8781, 29.7604, 33.4484, 39.9526], "Lon": [-74.0060, -118.2437, -87.6298, -95.3698, -112.0740, -75.1652] }) # 定义区间和对应颜色(区间边界对应数值的比例,比如0对应0,2000/50000=0.04,以此类推) color_scale = [ [0, "#e5f5f9"], [2000/50000, "#99d8c9"], [5000/50000, "#2ca25f"], [20000/50000, "#006d2c"], [1, "#006d2c"] # 最高区间的上限对应1(即50000) ] fig = go.Figure(go.Scattermapbox( lat=city_data["Lat"], lon=city_data["Lon"], mode="markers", marker=dict( size=city_data["EventCount"]/1000, # 缩放点的大小,避免纽约的点太大 color=city_data["EventCount"], colorscale=color_scale, cmin=0, cmax=50000, colorbar=dict( tickvals=[1000, 3500, 12500, 35000], # 色条刻度位置(对应每个区间的中间值) ticktext=["0-2000", "2001-5000", "5001-20000", "20001-50000"], # 刻度标签 title="事件次数", thickness=15 ), showscale=True ), # 悬停时显示的内容 text=[f"{city}<br>事件次数: {count}" for city, count in zip(city_data["City"], city_data["EventCount"])] )) fig.update_layout( mapbox_style="carto-positron", zoom=3, title="美国城市事件发生次数(离散色阶)" ) fig.show()
这个方案的优势:
不需要预先转换数据为分类字段,直接通过colorscale定义离散区间的颜色映射,色条的样式也能完全自定义,适合需要高度定制化的可视化场景。
额外小技巧:
- 如果是绘制 choropleth 地图,两种方案的逻辑完全通用:Express中用
color_discrete_map,Graph Objects中设置colorscale为离散区间即可。 - 可以给极端值区间设置更醒目的颜色(比如红色),让它在图中一眼就能被识别出来。
内容的提问来源于stack exchange,提问作者evangelist_17
相关产品推荐
相关产品推荐

