Add a color border to a specific polgygon in a plotly choropleth map

I plotted a choroplethmap with the following code:

fig = px.choropleth_mapbox(df,
                           geojson=df.geometry,
                           locations=df.index,
                           color="valu1",
                           color_continuous_scale='RdBu',
                           mapbox_style="open-street-map",
                           zoom=8)


fig.show()

Which returned this map:

image

So what I want is to set the edge color of a specific polygon that meets one condition. May be df.index=1(or any index) or df[df[ā€˜column_nameā€™]=='any_cell_value"] but Iā€™m not being able to do it.

I tried out this:

fig.for_each_trace(
    lambda trace: trace.update(marker_line_color="green") if selector==dict(column_name='any_cell_value') else (),
)

But it added green borders to all polygons. And I also tried out add_choroplethmapbox but Iā€™m getting several errors.

How could I do what that? Any ideas? Thank you!

If you create a JavaScript snippet (and put it in your assets folder) that defines the condition(s),

window.myNamespace = Object.assign({}, window.myNamespace, {
    geojsonExample: {
        style: function(feature, context) {
            if(feature.properties.name === context.props.hideout){
                return {color:'red'}
            }
            return {color:'grey'}
        }
    }
});

i.e. in this example ā€œcolor the polygon red if the name matches the hideout propā€, you could draw the polygons like this,

import dash
import dash_html_components as html
import dash_leaflet as dl
import dash_core_components as dcc
from dash.dependencies import Output, Input
from dash_extensions.javascript import Namespace

# Create geojson.
ns = Namespace("myNamespace", "geojsonExample")
geojson = dl.GeoJSON(url="/assets/us-states.json", zoomToBounds=True, id="geojson", options=dict(style=ns("style")))
# Create app.
app = dash.Dash()
app.layout = html.Div([dl.Map(children=[dl.TileLayer(), geojson]), dcc.Input(id="input", autoComplete="off")],
                      style={'width': '100%', 'height': '90vh', 'margin': "auto", "display": "block"}, id="map")


@app.callback(Output("geojson", "hideout"), [Input("input", "value")])
def update_selection(value):
    return value


if __name__ == '__main__':
    app.run_server()

which yields an application that looks like this,

1 Like

Thanks for your answer but I canā€™t totally understand the first part of the solution (the JavaScript snippet part) and how itā€™s integrated with the Dash app. Iā€™m new at dashboarding with python and Iā€™m kinda lost! :sweat:

@Emil btw, what I want is to set the color of the edge, not the color of the entire polygon

There is some official documentation on assets,

and i also wrote some docs on this kind of use case,

You can change any style property of the polygon, to change the edge color i guess you could keep the fillColor constant and change the color dynamically.

This is probably too late, but I couldnā€™t find a good answer anywhere so figured Iā€™d contribute.

My solution is pretty hacky, but I think achieves what you are trying to do.

I added additional choropleth traces with opacity 0 but with a thick marker line width/color. Iā€™m sure there is a more efficient way of doing this but the code below pulls out the specific geojson features that you want (by name) and creates a new trace for just that county (or country/state/province) with opacity 0 so it doesnā€™t block out your initial data, but still highlights the selected areas.

for i in range(len(df)):
        for c in counties['features']:
                if c['properties']['NAME'] == df['county'][i]:
                        break
        if c['properties']['NAME'] in ['Los Angeles', 'Miami-Dade', 'Suffolk']:
                fig.add_trace(go.Choropleth({"marker_line_color":"red",'featureidkey': 'properties.NAME',
                'geo': 'geo',"marker_line_width":2, 'geojson':c, 'z': [df['count'][i]], 'locations': [df['county'][i]], 'colorscale': [[0,'rgba(0,0,0,0)'],[1,'rgba(0,0,0,0)']], 'colorbar':None, 'showlegend': False}))