Skip to content

Instantly share code, notes, and snippets.

@FlorinAndrei
Created May 29, 2020 20:39
Show Gist options
  • Save FlorinAndrei/10ac545b7bdffc846d93ac572cb4b37a to your computer and use it in GitHub Desktop.
Save FlorinAndrei/10ac545b7bdffc846d93ac572cb4b37a to your computer and use it in GitHub Desktop.
#!/usr/bin/env python
# coding: utf-8
# In[1]:
import requests
import json
import os
import pandas as pd
import plotly.express as px
import copy
orca_in_docker = True
if orca_in_docker:
import plotly.io as pio
import time
pio.orca.config.server_url = "http://localhost:9091"
pio.orca.config.use_xvfb = False
print('import data')
# get GeoJSON for counties
# https://eric.clst.org/tech/usgeojson/
geofile = 'gz_2010_us_050_00_5m.json'
geourl = 'https://eric.clst.org/assets/wiki/uploads/Stuff/' + geofile
if not os.path.exists(geofile):
req = requests.get(geourl)
with open(geofile, 'wb') as f:
f.write(req.content)
with open(geofile, encoding='ISO-8859-1') as f:
counties = json.load(f)
# add geo id field compatible with the data format
for c in counties['features']:
c['id'] = c['properties']['GEO_ID'][-5:]
#counties
# In[2]:
# get unemployment data
unempfile = 'fips-unemp-16.csv'
unempurl = 'https://raw.githubusercontent.com/plotly/datasets/master/' + unempfile
if not os.path.exists(unempfile):
req = requests.get(unempurl)
with open(unempfile, 'wb') as f:
f.write(req.content)
unemp = pd.read_csv(unempfile,
dtype={"fips": str})
#unemp
# In[3]:
# now look for missing FIPS codes in data, and backfill them in from GeoJSON
# data will be all 0 for the backfilled rows
# without this, the map has holes in it
allcodes = [c['id'] for c in counties['features']]
for c in allcodes:
if c not in unemp['fips'].tolist():
newrow = {}
newrow.update({'fips': c})
for col in unemp.columns.tolist()[1:]:
newrow.update({col: 0})
unemp = unemp.append(newrow, ignore_index=True)
# In[4]:
# get GeoJSON data for states
# https://eric.clst.org/tech/usgeojson/
geostatefile = 'gz_2010_us_040_00_5m.json'
geostateurl = 'https://eric.clst.org/assets/wiki/uploads/Stuff/' + geostatefile
if not os.path.exists(geostatefile):
req = requests.get(geostateurl)
with open(geostatefile, 'wb') as f:
f.write(req.content)
with open(geostatefile) as f:
jstates = json.load(f)
#jstates
# In[5]:
print('convert states')
# convert states from Polygon to LineString
states = copy.deepcopy(jstates)
for k, feat in enumerate(jstates['features']):
if feat['geometry']['type']=='Polygon':
states['features'][k]['geometry']['type']='LineString'
states['features'][k]['geometry']['coordinates']=feat['geometry']['coordinates'][0]
elif feat['geometry']['type']=='MultiPolygon':
states['features'][k]['geometry']['type']='MultiLineString'
states['features'][k]['geometry']['coordinates']=[linea[0]
for linea in feat['geometry']['coordinates']]
else:
raise ValueError('geom-type is not polygon or multipolygon')
#states
# In[6]:
print('draw map')
fig = px.choropleth_mapbox(unemp,
geojson=counties,
locations='fips',
color='unemp',
color_continuous_scale="Inferno",
center={'lat': 38.5, 'lon': -95.77 },
zoom=4.42,
mapbox_style='carto-positron',
)
fig.update_layout(
title_text='<b>US unemployment</b>',
title_y=0.97,
title_font_size=32,
width=1920,
height=1080,
coloraxis_colorbar = {
'tickmode': 'array',
# fake nonlinear scale, just for testing
'tickvals': [0, 5, 10, 15, 20, 25],
'ticktext': [0, 0.5, 1, 3, 10, 25],
'title': 'unemployment',
},
margin={"r":0,"t":0,"l":0,"b":0},
mapbox_layers = [dict(sourcetype = 'geojson',
source = states,
color='#ffffff',
type = 'line',
line=dict(width=1)
)]
)
print('save map')
fig.write_image('bigmap.png', scale=1.0)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment