✊🏿 Black Lives Matter. Please consider donating to Black Girls Code today.
🧬 Learn how to build RNA-Seq data apps with Python & Dash. Register for the May 20 Webinar!

Choropleth - how to draw US state lines on top of counties map?

from urllib.request import urlopen
import json
import requests
import os
import pandas as pd
import plotly.express as px

geofile = 'geojson-counties-fips.json'
geourl = 'https://raw.githubusercontent.com/plotly/datasets/master/' + geofile
if not os.path.exists(geofile):
    req = requests.get(geourl)
    with open(geofile, 'wb') as f:
        f.write(req.content)

with open(geofile) as f:
    counties = json.load(f)

tsfile = 'time_series_covid19_confirmed_US.csv'
tsurl = 'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/' + tsfile

if not os.path.exists(tsfile):
    req = requests.get(tsurl)
    with open(tsfile, 'wb') as f:
        f.write(req.content)

ts = pd.read_csv(tsfile, dtype={"FIPS": float})
ts.dropna(inplace=True)
ts['FIPS'] = ts['FIPS'].astype('int64', copy=True)
ts = ts[ts['FIPS'] < 80000].copy(deep=True)
ts['FIPS'] = ts['FIPS'].astype('str', copy=True)

ts['FIPS'] = ts['FIPS'].str.rjust(5, '0')

ts_short = ts[['FIPS', '5/9/20', '5/10/20']].copy(deep=True)
ts_short['delta'] = ts_short['5/10/20'] - ts_short['5/9/20']
ts_short = ts_short[ts_short['delta'] >= 0].copy(deep=True)

dmin = ts_short['5/10/20'].min()
dmax = ts_short['5/10/20'].max()

fig = px.choropleth(ts_short, geojson=counties, locations='FIPS', color='5/10/20',
                           color_continuous_scale="Inferno",
                           range_color=(dmin, dmax),
                           scope="usa"
                          )

fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})

fig.show()

How to draw state lines on top of this map?

There’s no built in feature for this, but you might be able to layer on a second choropleth trace with thicker borders and a transparent fill?

I see - well, I understand the concept, and it’s more or less how I imagined it, but I literally started playing with Plotly a couple days ago and the implementation details of that are a mystery yet to me.

There are two problems I think I need to solve:

  1. How to add another map to the same image? (see code above) Is it a new fig object? Or do I add to the same fig?

  2. The second map would have to show only the US state borders in 1 px width, color=‘white’, and everything else would have to have whatever the rgba code is for transparency (unless there are options to dictate transparency for the other elements).

Any suggestion? It doesn’t have to be syntax-perfect - I’ll figure out the details if I know where to start. I’m honestly a bit lost in the documentation. Thank you!

(Making great progress otherwise, I’ve solved all the other problems thanks to the excellent suggestions I’ve received on this forum, and the map looks great. The only remaining issue is the missing state borders.)

@FlorinAndrei

In this Jupyter Notebook https://gist.github.com/empet/daf55214d7e61b361c6b0db3cef9a6e0 , I artificially created your case for the Swiss cantons.

First I defined a choroplethmapbox of cantons. Then from the same geojson file I extracted the LineString(s) representing the boundaries of cantons, and plotted these boundaries as layers associated to the initial figure.

I suppose that you cannot extract the US state boundaries from your geojson file of US counties. Hence you have to find out a geojson file on github or elsewhere, that represent the US states, at the same scale as your initial county geojson file. From the latter file extract, as I did in the above notebook, the US states boundaries, and add them as layers to your initial fig.

1 Like

@empet - that was great, thank you!

I followed your example and now I have this:

https://chart-studio.plotly.com/~florin.andrei/3

It replaces px.choropleth() with px.choropleth_mapbox().

I lose the nice scope="usa" shortcut, which means I lose Alaska and Hawaii. I think it would be hard to bring them back on the map (somehow I would have to render them separately), so I might have to live with that loss (sorry, AK and HI). Unless I could stick scope="usa" back into px.choropleth_mapbox() somehow? Zooming out until AK and HI appear on the map is not an option, the mainland would be too small.

How do I make everything else disappear (without using the magic scope="usa" shortcut)? Canada, Mexico, the oceans, along with several names, are now shown on the map. What are the attributes that control the color for those things? I don’t mind them too much, but I’d like to at least compare the “with” and the “without” versions.