使用Plotly绘制Choropleth图出现异常输出问题
问题背景
基于德国联邦地理信息局的官方Shapefile制作交互地图,Geopandas绘图完全正常,但Plotly生成的图像存在异常。
最小复现示例
Geopandas DataFrame(df)几何信息
POLYGON ((3531713.337678026 6077121.156487568, 3532465.753191419 6075813.698160076, 3532499.600608208 6073802.38080852, 3532628.620627062 6071581.931537509, 3531869.321592058 6071241.4429235915, 3530658.9527930534 6071452.139477672, 3529785.8865069808 6069639.599440108, 3528957.748991292 6069263.645501549, 3524438.372433494 6069362.957531026, 3523076.9337587883 6072388.279024946, 3525993.515925105 6073979.273399123, 3526059.8716776026 6077145.86655316, 3527321.4826777824 6077426.793668112, 3528119.236993772 6075749.876051087, 3527687.374944012 6074791.893603065, 3528096.1044506407 6073782.871432945, 3529905.083799622 6077114.618219143, 3531713.337678026 6077121.156487568))
CRS信息
return (<Derived Projected CRS: EPSG:31467> Name: DHDN / 3-degree Gauss-Kruger zone 3 Axis Info [cartesian]: - X[north]: Northing (metre) - Y[east]: Easting (metre) Area of Use: - name: Germany - former West Germany onshore between 7°30'E and 10°30'E - states of Baden-Wurtemberg, Bayern, Bremen, Hamberg, Hessen, Niedersachsen, Nordrhein-Westfalen, Rhineland-Pfalz, Schleswig-Holstein. - bounds: (7.5, 47.27, 10.51, 55.09) Coordinate Operation: - name: 3-degree Gauss-Kruger zone 3 - method: Transverse Mercator Datum: Deutsches Hauptdreiecksnetz - Ellipsoid: Bessel 1841 - Prime Meridian: Greenwich )
已尝试代码
Geopandas绘图(正常显示)
df.geometry.plot()
Plotly绘图(异常)
fig = px.choropleth(df, geojson=df.geometry, locations=df.index) fig.show()
已排查步骤
- 将CRS从EPSG:31467转换为EPSG:3395,设置
projection='mercator',仍异常 - 设置
fitbounds参数,无效 - 手动转换
df.geometry为GeoJSON并验证索引对应关系,未解决问题
解决方案
Plotly Express的choropleth默认要求WGS84(EPSG:4326)地理坐标系的GeoJSON,且坐标顺序为[经度, 纬度]。非Web墨卡托类的投影坐标系(如Gauss-Kruger)无法被Plotly正确解析,需按以下步骤处理:
1. 转换为WGS84地理坐标系
先将数据转换为经纬度格式:
df_wgs84 = df.to_crs(epsg=4326)
2. 使用规范的GeoJSON接口
利用GeoPandas内置的__geo_interface__生成符合Plotly要求的GeoJSON结构,同时指定featureidkey匹配索引:
import plotly.express as px fig = px.choropleth(df_wgs84, geojson=df_wgs84.geometry.__geo_interface__, locations=df_wgs84.index, featureidkey="id") # 自动适配图层边界 fig.update_geos(fitbounds="locations", visible=False) fig.show()
3. 替代方案:使用Plotly Graph Objects
若上述方法仍有问题,可直接用go.Choropleth手动构建图层,灵活性更高:
import plotly.graph_objects as go fig = go.Figure(go.Choropleth( geojson=df_wgs84.geometry.__geo_interface__, locations=df_wgs84.index, z=[1], # 替换为你的数据列 featureidkey="id" )) fig.update_geos(fitbounds="locations", visible=False) fig.show()
关键原因说明
- Plotly对非Web墨卡托的投影坐标系支持有限,必须转换为WGS84经纬度才能正确解析
__geo_interface__是GeoPandas内置的标准GeoJSON接口,比直接传入df.geometry更可靠,能确保GeoJSON包含id字段与locations参数匹配
内容的提问来源于stack exchange,提问作者Metrics_Hannah

