Hey everyone. I have been trying to render shapefiles from the UK’s Open Geography Portal specifically here https://geoportal.statistics.gov.uk/datasets/local-authority-districts-december-2019-boundaries-uk-bfc.
I have been able to use mapshaper.org and QGis to successfully render these polygons, but I would really would prefer to do this in Python within JupyterLab. I have followed many tutorials on how to convert .shp files to geoJson and have been able to successfully render the examples provided by @empet such as https://plotly.com/~empet/15238/tips-to-get-a-right-geojson-dict-to-defi/ and https://plotly.com/~empet/15237/choroplethmapbox-with-dropdown-menu/#/. After trying these methods to no avail I tried different ways of inserting the id
key but again they didn’t render.
I have tried both creating an artificial ‘id’ and using the plotly featurekeyid
field but neither of them are working. When I do use the id
key, I have checked that the id
key is in the correct location.
Sometimes the base mapbox layer will render but no polygons and others the code will run and then hang. Please see below code as to what I have been implementing. This is an example of trying to render Local Authority Boundaries:
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()
This does not render as I say. I have tried using a list of values from a different df too not just synthetic data with the corresponding locations
field from that df too matching the id
key. What I am expecting are the following polygons on top of the Mapbox base layer. This image was generated on mapshaper:
I have also tried reducing the size of the .shp file using mapshaper’s various algorithms then saving that to geoJSON format and skipping the conversion step in Python from .shp to geoJSON but again to no avail. Also changing the tolerance
in the shapely
manipulation does not seem to change the output.
My mapbox access token is valid.
Does anyone have any idea what could be causing the issue? I’m assuming the .shp files are fine as they are rendered fine on mapshaper and QGis. Any help would be greatly appreciated.
Thank you.