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

Plotly Choropleth Mapbox无法正确渲染GeoJSON:映射/几何问题排查

解决Plotly choropleth_mapbox电力竞价区域渲染及交互问题

一、修复投影转换失效问题

投影错误是地图显示随机形状的核心原因,按以下步骤确保转换生效:

  • 加载Shapefile时强制指定原CRS:GeoPandas若无法自动识别Shapefile的投影(无.prj文件),重投影会直接失效。先确认原数据的EPSG代码(比如欧洲常用的EPSG:3035),再执行:
import geopandas as gpd

# 加载并指定原CRS
gdf = gpd.read_file("bidding_zones.shp")
if gdf.crs is None:
    gdf = gdf.set_crs("EPSG:3035")  # 替换为你的原投影EPSG代码

# 重投影至WGS84(EPSG:4326)
gdf = gdf.to_crs("EPSG:4326")
  • 验证转换结果:打印gdf.geometry.head(),确认坐标值在±180(经度)、±90(纬度)范围内,而非大数值的投影坐标。
  • 正确导出GeoJSON:用GeoPandas内置方法避免手动处理出错:
geojson_data = gdf[["zoneName", "geometry"]].to_json()

二、修复代码变量与语法错误

  • 定义匹配的测试数据:确保zoneName与GeoJSON中的字段完全一致(大小写、空格、缩写必须严格匹配),同时包含电价、年月字段:
import pandas as pd
import numpy as np

# 生成与GeoJSON匹配的测试数据
test_data = pd.DataFrame({
    "zoneName": gdf["zoneName"].tolist(),
    "price": np.random.randint(0, 100, len(gdf)),
    "year": 2024,
    "month": np.random.randint(1, 13, len(gdf))
})
  • 检查choropleth_mapbox参数对应关系:核心参数必须精准匹配:
    • geojson:传入转换后的GeoJSON字符串
    • locations:数据中用于匹配的列(即zoneName)
    • featureidkey:GeoJSON中属性的路径,固定为properties.zoneName

三、基础可渲染地图代码

import plotly.express as px

fig = px.choropleth_mapbox(
    test_data,
    geojson=geojson_data,
    locations="zoneName",
    featureidkey="properties.zoneName",
    color="price",
    color_continuous_scale="Viridis",
    mapbox_style="carto-positron",
    zoom=3,
    center={"lat": 50, "lon": 10},  # 对应欧洲区域中心
    opacity=0.7,
    labels={"price": "现货平均电价"}
)

fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()

四、添加年月筛选交互

通过Plotly的updatemenus实现下拉筛选,按年月组合过滤数据:

# 生成所有年月筛选选项
year_month_options = []
unique_years = test_data["year"].unique()
for year in unique_years:
    sorted_months = sorted(test_data[test_data["year"] == year]["month"].unique())
    for month in sorted_months:
        year_month_options.append(
            dict(
                label=f"{year}年{month}月",
                method="update",
                args=[
                    {"visible": (test_data["year"] == year) & (test_data["month"] == month)},
                    {"title": f"{year}年{month}月 电力现货平均电价"}
                ]
            )
        )

# 集成筛选菜单到布局
fig.update_layout(
    updatemenus=[
        dict(
            buttons=year_month_options,
            direction="down",
            showactive=True,
            x=0.1,
            xanchor="left",
            y=1.1,
            yanchor="top"
        )
    ],
    title="电力竞价区域现货平均电价"
)

fig.show()

关键排查要点

  1. 字段匹配:zoneName在数据和GeoJSON中必须完全一致,包括大小写、空格、特殊字符
  2. 投影验证:重投影后必须确认坐标为WGS84经纬度范围
  3. GeoJSON结构:用文本编辑器打开GeoJSON,确认features[*].properties.zoneName存在且值正确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 06:12:36