Plotly choropleth_mapbox 的 GeoJSON 问题

Jki*_*fn1 6 python pandas plotly geopandas

我通过创建 choropleth 地图的方法plotly似乎非常简单——加载到 DataFrame 中,加载到 geojson 中,将必要的特征分配给自定义多边形,然后绘制。

显然,在引用自定义多边形时在某处遗漏了一个步骤,因为在漫长的加载时间后只会出现一张空白地图。

需要注意的一件主要事情是,大约一半的多边形位于州内,但它们是州内的自定义多边形。因此,据我所知,choropleth_mapbox是更合适的解决方案。

图像示例,显示各州内的自定义多边形: 在此处输入图片说明

编码:

import pandas as pd
import plotly.express as px
import geopandas as gpd
from geojson import Polygon
import json

# reading in the dataframe
path = '/path/to/csv'
df = pd.read_csv(path)
geo_df = gpd.GeoDataFrame(df)

# reading in the geospatial data
with open('/path/to/geojson') as f:
    geojson = json.load(f)
    
# create the plot
fig = px.choropleth_mapbox(geo_df[0:50], #slicing for quick loading
                           geojson=geojson, 
                           color="MALL",
                           locations="MWS_ID", 
                           featureidkey="properties.MWS_ID",
                           center={"lat": 39, 
                                   "lon": -95},
                           mapbox_style="carto-positron", 
                           zoom=3)

fig.show()
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明

显然数据缺失。

我认为问题出在 geojson 文件中。我能看到的关于 geojson 结构的唯一可能是我的 geojson 的坐标在两个括号中,而文档坐标中的 geojson 在三个括号中。

下面是我的 geojson。

{'type': 'FeatureCollection',
 'features': [{'type': 'Feature',
   'geometry': {'type': 'Polygon',
    'coordinates': [[-89.299965, 36.508405],
     [-89.414355, 36.499866],
     [-89.424498, 36.476321],
     .....
   'properties': {'MWS_ID': 'TN_1'}},

  {'type': 'Feature',
   'geometry': {'type': 'Polygon',
    'coordinates': [[-111.043999, 44.139903],
     [-111.040171, 42.227952],
     [-111.040773, 41.820698],
     .....
Run Code Online (Sandbox Code Playgroud)

下面是文档的 geojson

{'type': 'FeatureCollection',
 'features': [{'type': 'Feature',
   'geometry': {'type': 'MultiPolygon',
    'coordinates': [[[[-73.6363215300962, 45.5759177646435],
       [-73.6362833815582, 45.5758266113331],
       .....
       [-73.6363215300962, 45.5759177646435]]],
     [[[-73.6561004885273, 45.5841347974261],
       .....
       [-73.6561004885273, 45.5841347974261]]]]},
   'properties': {'district': '11-Sault-au-Récollet'},
   'id': '11'},

  {'type': 'Feature',
   'geometry': {'type': 'Polygon',
    'coordinates': [[[-73.6217484540132, 45.5544783077209],
      [-73.6235005117779, 45.5536358848324],
      [-73.6278096771011, 45.5513024018691],
Run Code Online (Sandbox Code Playgroud)

这是我创建 geojson 的方法

# Create the GeoJSON
names_merged = names_1 + names_2
geoms_merged = geoms_1 + geoms_2

geojson = {'type':'FeatureCollection', 'features':[]}

for i in range(len(names_merged)):
    feature = Feature(geometry=geoms_merged[i])
    geojson['features'].append(feature)
    geojson['features'][i]['properties']['MWS_ID'] = names_merged[i]
    
with open('/path/to/geojson', 'w') as f:
   dump(geojson, f)
Run Code Online (Sandbox Code Playgroud)

其中,names_merged 是str格式中的 MWS_ID 列表,geoms_merged 是格式中的多边形列表geojson.geometry.Polygon

验证数据框和 geojson 具有相同的键。

print(geo_df['MWS_ID'][3])
print(geojson["features"][28]['properties']["MWS_ID"])
Run Code Online (Sandbox Code Playgroud)

输出

AZ_2
AZ_2
Run Code Online (Sandbox Code Playgroud)

但地图仍然是空白的。

感谢您对 SO 社区的持续帮助。

zer*_*iME 5

您的输出不是 choropleth_mapbox,而是 choropleth。您是否缺少向我们展示任何布局代码?如果没有看到所有代码,就很难确定问题的根本原因,因此我将向您展示一个简单的工作示例,说明如何将 geojson 连接到数据框并将其显示为下面的 choropleth_mapbox。

import pandas as pd
import plotly.express as px

df = pd.DataFrame({'letter':['A','B','C'],'name':['AZ_1','BV_2','CD_3'],'value':[2,5,7]})


gj = {
    'type': 'FeatureCollection',
    'features': [
        {
            'type': 'Feature',
            'geometry': {
                'type': 'Polygon',
                'coordinates':[[
                    [-82.899205,33.653817],
                    [-82.771500,32.516301],
                    [-80.914171,32.133138],
                    [-79.710831,33.171969],
                    [-82.899205,33.653817]
                ]]
            },
            'properties': {'unique_id': 'AZ_1', 'name': 'shape A'}
        },
                {
            'type': 'Feature',
            'geometry': {
                'type': 'Polygon',
                'coordinates':[[
                    [-80.883651,33.080687],
                    [-80.835692,33.797411],
                    [-82.095711,34.396734],
                    [-82.945897,33.168320],
                    [-80.883651,33.080687]
                ]]
            },
            'properties': {'unique_id': 'BV_2', 'name': 'shape B'}
        },
                {
            'type': 'Feature',
            'geometry': {
                'type': 'Polygon',
                'coordinates':[[
                    [-79.471035,33.255865],
                    [-78.202296,34.086771],
                    [-78.629569,34.855954],
                    [-81.446082,34.698384],
                    [-79.471035,33.255865]
                ]]
            },
            'properties': {'unique_id': 'CD_3', 'name': 'shape C'}
        },
    ]
}

fig = px.choropleth_mapbox(df, geojson=gj,color=df.value,
                           locations=df.name, featureidkey="properties.unique_id",
                           center={"lat": 33.33012299999999, "lon": -81.08463033333332},
                           mapbox_style="carto-positron", zoom=5)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
Run Code Online (Sandbox Code Playgroud)

当将 geojson 与自定义多边形一起使用时,您只需确保与数据帧列featureidkey匹配locations,以便您可以将其他数据帧值应用于多边形(例如颜色、文本等)。

上面的简单代码应该输出:在此输入图像描述 这就是 choropleth_mapbox 应该输出的内容 - 基于图块的地图。您的输出不是基于图块的,这就是为什么我询问您是否有额外的布局代码来更改显示的地图类型。即使您的 choropleth_mapbox 格式错误,输出也不会是您所拥有的。

编辑答案

您的 geojson 格式错误 - 多边形坐标数组应该是 3 维数组而不是 2 维。运行以下代码来更新坐标数组:

old_features = [feature for feature in geojson['features']]
new_features = [feature for feature in geojson['features']]
for i in range(len(old_features)):
    new_features[i]['geometry']['coordinates'] = [new_features[i]['geometry']['coordinates']]
new_geojson = {
    'type': 'FeatureCollection',
    'features': new_features
Run Code Online (Sandbox Code Playgroud)

现在创建地图应该可以了:

fig = px.choropleth_mapbox(df, geojson=new_geojson,color=df.MALL,
                           locations=df.MWS_ID, featureidkey="properties.MWS_ID",
                           center={"lat": 39, "lon": -95},
                           mapbox_style="carto-positron", zoom=3)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()
}
Run Code Online (Sandbox Code Playgroud)

这是我使用 csv 和 geojson 得到的输出:

在此输入图像描述