Plotly choropleth : deal with union of polygons and borders

73 Views Asked by At

I'm trying to make a choropleth map of cities in France (which means color the city in a scale). But, I'd like to enhance border of departments (which are a connex union of cities)

I manage to create a geo-json file with both cities and departments (as union of polygons of cities with Shapely library). The geo-json dictionary contains features (each polygon with a unique properties.code : department are like '76' and cities like '76000' as string)

I'd like to color the cities (by Choropeth) and borders departments (color is empty or opacity = 0). Thanks to first answer, I tried the code below but it doesn't work (either I color the cities and get their borders, or I color cities and departments (with 'val' filled) and gets them all colored but departments hide cities)

list_rnd = np.random.randint(0,100,size=len(set_commune))
df_commune = pd.DataFrame({'code':list(set_commune), 'val':list_rnd})
df_commune['dept'] = df_commune.code.map(lambda x:x[:2])
df_commune['lineWidth'] = 1
df_commune['lineColor'] = 'grey'

df_dept = pd.DataFrame({'code':['27', '76'], 'val':None})
df_dept['lineWidth'] = 3
df_dept['lineColor'] = 'red'

df_total = pd.concat([ df_commune, df_dept])

fig = go.Figure(data=go.Choropleth(
            geojson=geojson_all_levels,
            locations=df_total['code'],
            z=df_total['val'].astype(float), 
            featureidkey='properties.code', 
            colorscale='Viridis',
            colorbar_title='Nombre de demandes',
            marker_line_width=df_total['lineWidth'],
            marker_line_color=df_total['lineColor'],
))

I also heard about updated_traces but without making it worked

1

There are 1 best solutions below

2
On

As a customization of the map, a way to highlight specific boundaries requires the use of a graph object. Since your question does not present geojson data, I have created more appropriate sample data, taken from here. I have created a list of line widths for the total number of counties and a list of colors for the line colors, and I have changed some of the line widths and line colors for the markers, but I have used featureidkey='properties.code' because I need to associate it with geojson, but your geojson data uses ' properties.id' in your geojson data.

edit: The question has been corrected and the code has been modified. You need to update the row data for a specific region, e.g. .iloc. You are adding data to the ... And if the data value is None, it will not be drawn, including the boundaries, so I used an appropriate negative value.

import plotly.graph_objects as go
from urllib import request
import json
import pandas as pd
import numpy as np

np.random.seed(1)
url = 'https://raw.githubusercontent.com/gregoiredavid/france-geojson/master/departements-version-simplifiee.geojson'
with request.urlopen(url) as f:
    fr_departments = json.load(f)

departments = []
for i in range(len(fr_departments['features'])):
    department = fr_departments['features'][i]['properties']
    departments.append([department['code'], department['nom']])

df = pd.DataFrame(departments, columns=['code','nom'])

list_rnd = np.random.randint(0,100,size=len(df))
df_commune = pd.DataFrame({'code':df['code'].tolist(), 'val':list_rnd})
df_commune['dept'] = df_commune.code.map(lambda x:x[:2])
df_commune['lineWidth'] = 1
df_commune['lineColor'] = 'grey'

update_data1 = ['27', -10, 27, 3, 'red']
update_data2 = ['76', -10, 76, 3, 'red']
df_commune.iloc[25] = update_data1
df_commune.iloc[76] = update_data2
df_total = df_commune.copy()

fig = go.Figure(data=go.Choropleth(
            geojson=fr_departments,
            locations=df_total['code'],
            z=df_total['val'].astype(float), 
            featureidkey='properties.code', 
            colorscale='Viridis',
            colorbar_title='Nombre de demandes',
            marker_line_width=df_total['lineWidth'],
            marker_line_color=df_total['lineColor'],
))
fig.update_geos(fitbounds="locations", visible=False)
fig.update_layout(height=500)

fig.show()

enter image description here