Plotly 没有渲染 Choropleth Mapbox Polygons
Plotly is not rendering Choropleth Mapbox Polygons
转换 shapefile 来在 Plotly 中渲染 geoJSON
plotly.graph_objects.Choroplethmapbox
的 Python Plotly 文档提到在 geoJSON 中每个特征都需要一个 id
字段。我尝试过创建人工 id
和使用 plotly featurekeyid
字段,但它们都不起作用。当我确实使用 id
键时,我检查了 id
键是否在正确的位置,并尝试了 int64 和字符串。
有时基础 mapbox 图层会呈现但没有多边形,而其他情况下代码会 运行 然后挂起。
我还尝试使用 mapshaper 的各种算法减小 .shp 文件的大小,然后将其保存为 geoJSON 格式并跳过 Python 中从 .shp 到 geoJSON 的转换步骤,但再次无济于事。在 shapely
操作中更改 tolerance
似乎也不会更改输出。
我期待的是一个带有 mapbox 基础层的地图投影,地方当局区多边形在顶部并被填充。下面的 link 显示了多边形,创建于 mapshaper.org:
Polygons of Local Authority District
我的 mapbox 访问令牌有效。
这是一个尝试通过添加 id
字段并将 .shp 文件转换为 geoJSON 然后创建跟踪来呈现地方当局边界多边形的示例:
import geopandas as gpd
from shapely.geometry import LineString, MultiLineString
import plotly.graph_objs as go
# load in shp files
lad_shp = gpd.read_file('zip://../../data/external/Local_Authority_Districts_(December_2019)_Boundaries_UK_BFC-shp.zip', encoding='utf-8')
# using empet code to convert .shp to geoJSON
def shapefile_to_geojson(gdf, index_list, tolerance=0.025):
# gdf - geopandas dataframe containing the geometry column and values to be mapped to a colorscale
# index_list - a sublist of list(gdf.index) or gdf.index for all data
# tolerance - float parameter to set the Polygon/MultiPolygon degree of simplification
# returns a geojson type dict
geo_names = list(gdf[f'lad19nm']) # name of authorities
geojson = {'type': 'FeatureCollection', 'features': []}
for index in index_list:
geo = gdf['geometry'][index].simplify(tolerance)
if isinstance(geo.boundary, LineString):
gtype = 'Polygon'
bcoords = np.dstack(geo.boundary.coords.xy).tolist()
elif isinstance(geo.boundary, MultiLineString):
gtype = 'MultiPolygon'
bcoords = []
for b in geo.boundary:
x, y = b.coords.xy
coords = np.dstack((x,y)).tolist()
bcoords.append(coords)
else: pass
feature = {'type': 'Feature',
'id' : index,
'properties': {'name': geo_names[index]},
'geometry': {'type': gtype,
'coordinates': bcoords},
}
geojson['features'].append(feature)
return geojson
geojsdata = shapefile_to_geojson(lad_shp, list(lad_shp.index))
# length to generate synthetic data for z attribute
L = len(geojsdata['features'])
# check id key is there
geojsdata['features'][0].keys()
>> dict_keys(['type', 'id', 'properties', 'geometry'])
# example of authroity name
geojsdata['features'][0]['properties']['name']
>> 'Hartlepool'
# check id
k=5
geojsdata['features'][k]['id']
>> '5'
trace = go.Choroplethmapbox(z=np.random.randint(10, 75, size=L), # synthetic data
locations=[geojsdata['features'][k]['id'] for k in range(L)],
colorscale='Viridis',
colorbar=dict(thickness=20, ticklen=3),
geojson=geojsdata,
text=regions,
marker_line_width=0.1, marker_opacity=0.7)
layout = go.Layout(title_text='UK LAD Choropleth Demo',
title_x=0.5,
width=750,
height=700,
mapbox=dict(center=dict(lat=54, lon=-2),
accesstoken=mapbox_access_token,
zoom=3))
fig=go.Figure(data=[trace], layout =layout)
fig.show()
上述 shapefile_to_geojson
函数的 geoJSON 输出可以在这里找到:https://www.dropbox.com/s/vuf3jtrr2boq5eg/lad19-geo.json?dl=0
有谁知道是什么导致了这个问题?我假设 .shp 文件很好,因为它们在 mapshaper.org 和 QGis 上渲染得很好。任何帮助将不胜感激。
谢谢。
只需更改投影系统即可纠正错误。在转换为 geoJSON 之前执行此操作:
lad_shp = lad_shp.to_crs(epsg=4326)
plotly.graph_objects.Choroplethmapbox
的 Python Plotly 文档提到在 geoJSON 中每个特征都需要一个 id
字段。我尝试过创建人工 id
和使用 plotly featurekeyid
字段,但它们都不起作用。当我确实使用 id
键时,我检查了 id
键是否在正确的位置,并尝试了 int64 和字符串。
有时基础 mapbox 图层会呈现但没有多边形,而其他情况下代码会 运行 然后挂起。
我还尝试使用 mapshaper 的各种算法减小 .shp 文件的大小,然后将其保存为 geoJSON 格式并跳过 Python 中从 .shp 到 geoJSON 的转换步骤,但再次无济于事。在 shapely
操作中更改 tolerance
似乎也不会更改输出。
我期待的是一个带有 mapbox 基础层的地图投影,地方当局区多边形在顶部并被填充。下面的 link 显示了多边形,创建于 mapshaper.org:
Polygons of Local Authority District
我的 mapbox 访问令牌有效。
这是一个尝试通过添加 id
字段并将 .shp 文件转换为 geoJSON 然后创建跟踪来呈现地方当局边界多边形的示例:
import geopandas as gpd
from shapely.geometry import LineString, MultiLineString
import plotly.graph_objs as go
# load in shp files
lad_shp = gpd.read_file('zip://../../data/external/Local_Authority_Districts_(December_2019)_Boundaries_UK_BFC-shp.zip', encoding='utf-8')
# using empet code to convert .shp to geoJSON
def shapefile_to_geojson(gdf, index_list, tolerance=0.025):
# gdf - geopandas dataframe containing the geometry column and values to be mapped to a colorscale
# index_list - a sublist of list(gdf.index) or gdf.index for all data
# tolerance - float parameter to set the Polygon/MultiPolygon degree of simplification
# returns a geojson type dict
geo_names = list(gdf[f'lad19nm']) # name of authorities
geojson = {'type': 'FeatureCollection', 'features': []}
for index in index_list:
geo = gdf['geometry'][index].simplify(tolerance)
if isinstance(geo.boundary, LineString):
gtype = 'Polygon'
bcoords = np.dstack(geo.boundary.coords.xy).tolist()
elif isinstance(geo.boundary, MultiLineString):
gtype = 'MultiPolygon'
bcoords = []
for b in geo.boundary:
x, y = b.coords.xy
coords = np.dstack((x,y)).tolist()
bcoords.append(coords)
else: pass
feature = {'type': 'Feature',
'id' : index,
'properties': {'name': geo_names[index]},
'geometry': {'type': gtype,
'coordinates': bcoords},
}
geojson['features'].append(feature)
return geojson
geojsdata = shapefile_to_geojson(lad_shp, list(lad_shp.index))
# length to generate synthetic data for z attribute
L = len(geojsdata['features'])
# check id key is there
geojsdata['features'][0].keys()
>> dict_keys(['type', 'id', 'properties', 'geometry'])
# example of authroity name
geojsdata['features'][0]['properties']['name']
>> 'Hartlepool'
# check id
k=5
geojsdata['features'][k]['id']
>> '5'
trace = go.Choroplethmapbox(z=np.random.randint(10, 75, size=L), # synthetic data
locations=[geojsdata['features'][k]['id'] for k in range(L)],
colorscale='Viridis',
colorbar=dict(thickness=20, ticklen=3),
geojson=geojsdata,
text=regions,
marker_line_width=0.1, marker_opacity=0.7)
layout = go.Layout(title_text='UK LAD Choropleth Demo',
title_x=0.5,
width=750,
height=700,
mapbox=dict(center=dict(lat=54, lon=-2),
accesstoken=mapbox_access_token,
zoom=3))
fig=go.Figure(data=[trace], layout =layout)
fig.show()
上述 shapefile_to_geojson
函数的 geoJSON 输出可以在这里找到:https://www.dropbox.com/s/vuf3jtrr2boq5eg/lad19-geo.json?dl=0
有谁知道是什么导致了这个问题?我假设 .shp 文件很好,因为它们在 mapshaper.org 和 QGis 上渲染得很好。任何帮助将不胜感激。
谢谢。
只需更改投影系统即可纠正错误。在转换为 geoJSON 之前执行此操作:
lad_shp = lad_shp.to_crs(epsg=4326)