Plotly 的 GeoJSON 问题 choropleth_mapbox

GeoJSON issues with Plotly choropleth_mapbox

我通过 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()

输出:

显然缺少数据。

我认为问题出在 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],
     .....

下面是文档的 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],

这是我创建 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)

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

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

print(geo_df['MWS_ID'][3])
print(geojson["features"][28]['properties']["MWS_ID"])

输出

AZ_2
AZ_2

但是地图还是空白。

感谢您一直以来的帮助S.O。社区。

您的输出不是 choropleth_mapbox,它是等值线。您是否缺少向我们展示任何布局代码?如果没有看到您的所有代码,就很难确定问题的根本原因,因此我将向您展示一个简单的工作示例,说明如何将 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()

当使用带有自定义多边形的 geojson 时,您只需确保 featureidkeylocations 数据框列相匹配,以便您可以将其他数据框值应用于多边形(如颜色、文本等)。

上面的简单代码应该输出: 这就是 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

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

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()
}

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