✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
⚡️ Concerned about the grid? Kyle Baranko teaches how to predicting peak loads using XGBoost. Register for the August webinar!

Adding state lines to county-level GeoJSON based choropleth

I’ve been able to use plotly.express to create a county-level choropleth using county GeoJSON data.

I was asked whether I can add state outlines to the map. Anyone have any ideas?

I’m using:

fig = px.choropleth(gdp_g_2018,

                geojson=counties, 

                locations='fips', 

                color='bins',

                category_orders = {'bins':lbls},

                projection = 'albers usa',

                scope="usa",

                labels={'bins':'Percent of 2018 GDP from Goods Producing Industries',

                        'fips':'FIPS Code'}

                )

I tried to update the map afterwards using:
fig.update_geos(

scope="usa",

showcountries=True, countrycolor="Black",

showsubunits=True, subunitcolor="Blue"

)

… but that doesn’t seem to work.

Thanks in advance for the help!

Hi @RNKuhns welcome to the forum! You were quite close actually I think, but you need to remove the boundaries between counties to be able to distinguish states boudaries. Adapting below an example from the plotly doc:

from urllib.request import urlopen
import json
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
                   dtype={"fips": str})

import plotly.express as px

fig = px.choropleth(df, geojson=counties, locations='fips', color='unemp',
                           color_continuous_scale="Viridis",
                           range_color=(0, 12),
                           scope="usa",
                           labels={'unemp':'unemployment rate'},                 
                          )
fig.update_traces(marker_line_width=0, marker_opacity=0.8)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.update_geos(
showsubunits=True, subunitcolor="black"
)
fig.show()

image

1 Like

Thanks for the welcome to the forum and the help.

I’ve actually just started picking up plotly this week. Besides the standard examples, do you have any suggestions for other resources to pick up some of these type of details?

Great to have you on board :-). And how to find documentation / information is a great question. We’re trying to have the plotly documentation https://plot.ly/python/ as complete as possible but there is always room for improvement, and we welcome ideas about examples to add to the doc.

When you get started, it is useful to read the tutorials of the Plotly fundamentals chapter, because these explain some fundamental concepts of the library. This is where you find explanations about the “magical underscore notation” marker_line_width, in https://plot.ly/python/creating-and-updating-figures/#magic-underscore-notation. Probably this Plotly fundamentals chapter should be expanded a bit, though.

It can be useful to inspect / explore the documentation of the API, especially for the graph_objects module: https://plot.ly/python-api-reference/plotly.graph_objects.html. Every trace has a corresponding module (e.g. go.choropleth for go.Choropleth), when you see that go.choropleth has a Marker object (and a corresponding go.choropleth.marker submodule) you can keep on exploring until you find the go.choropleth.marker.Line object which has a width attribute. I also do a lot of print(fig) to know what is defined in the figure. Happy plotting ;-).

Now try Inferno instead of Viridis, and use data that’s biased towards low values - so most counties are very dark. Then this technique doesn’t work.

Is there a more reliable solution to layer state borders on top of this map?

Let me be more specific. How to make state borders visible here…

from urllib.request import urlopen
import json
with urlopen('https://raw.githubusercontent.com/plotly/datasets/master/geojson-counties-fips.json') as response:
    counties = json.load(response)

import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/fips-unemp-16.csv",
                   dtype={"fips": str})

df.at[10, 'unemp'] = 1000

import plotly.express as px

fig = px.choropleth(df, geojson=counties, locations='fips', color='unemp',
                           color_continuous_scale="Inferno",
                           scope="usa",
                           labels={'unemp':'unemployment rate'},
                           width=1920,
                           height=1080,
                          )
fig.update_traces(marker_line_width=0, marker_opacity=1)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.update_geos(
showsubunits=True, subunitcolor="blue"
)
fig.show()

…without diluting the color scheme with marker_opacity < 1 The Inferno scheme loses its impact when it’s transparent, so diluted opacity is not a viable solution.

subunitcolor doesn’t matter, anything would work as long as it provides contrast.

How to solve this?

Is there any way to draw state lines on top of the map, as opposed to making the map transparent to reveal state lines?

Suggestion:

(1) plot choropleth using county geojson
(2) add US state geojson as trace, update line color and fill color as you wish
(3) disable basemap