USA County Choropleth Maps in Python

How to create colormaped representations of USA counties by FIPS values in Python.


Plotly Studio: Transform any dataset into an interactive data application in minutes with AI. Try Plotly Studio now.

Deprecation warning

This page describes a legacy "figure factory" method for creating map-like figures using self-filled scatter traces. This is no longer the recommended way to make county-level choropleth maps, instead we recommend using a GeoJSON-based approach to making outline choropleth maps or the alternative tile-based choropleth maps.

Required Packages

plotly_geo, geopandas, pyshp and shapely must be installed for this figure factory to run.

Run the following commands to install the correct versions of the following modules:

In [1]:
!pip install plotly-geo==1.0.0
!pip install geopandas==0.8.1
!pip install pyshp==2.1.2
!pip install shapely==1.7.1
Defaulting to user installation because normal site-packages is not writeable
Collecting plotly-geo==1.0.0
  Downloading plotly_geo-1.0.0-py3-none-any.whl.metadata (834 bytes)
Downloading plotly_geo-1.0.0-py3-none-any.whl (23.7 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 23.7/23.7 MB 56.7 MB/s eta 0:00:00
Installing collected packages: plotly-geo
Successfully installed plotly-geo-1.0.0
Defaulting to user installation because normal site-packages is not writeable
Collecting geopandas==0.8.1
  Downloading geopandas-0.8.1-py2.py3-none-any.whl.metadata (892 bytes)
Collecting pandas>=0.23.0 (from geopandas==0.8.1)
  Downloading pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl.metadata (79 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 79.5/79.5 kB 3.0 MB/s eta 0:00:00
Collecting shapely (from geopandas==0.8.1)
  Downloading shapely-2.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.metadata (6.8 kB)
Collecting fiona (from geopandas==0.8.1)
  Downloading fiona-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (56 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 56.6/56.6 kB 1.6 MB/s eta 0:00:00
Collecting pyproj>=2.2.0 (from geopandas==0.8.1)
  Downloading pyproj-3.7.2-cp312-cp312-manylinux_2_28_x86_64.whl.metadata (31 kB)
Collecting numpy>=1.26.0 (from pandas>=0.23.0->geopandas==0.8.1)
  Downloading numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.metadata (6.6 kB)
Requirement already satisfied: python-dateutil>=2.8.2 in /usr/lib/python3/dist-packages (from pandas>=0.23.0->geopandas==0.8.1) (2.8.2)
Requirement already satisfied: certifi in /usr/lib/python3/dist-packages (from pyproj>=2.2.0->geopandas==0.8.1) (2023.11.17)
Requirement already satisfied: attrs>=19.2.0 in /usr/lib/python3/dist-packages (from fiona->geopandas==0.8.1) (23.2.0)
Requirement already satisfied: click~=8.0 in /usr/lib/python3/dist-packages (from fiona->geopandas==0.8.1) (8.1.6)
Collecting click-plugins>=1.0 (from fiona->geopandas==0.8.1)
  Downloading click_plugins-1.1.1.2-py2.py3-none-any.whl.metadata (6.5 kB)
Collecting cligj>=0.5 (from fiona->geopandas==0.8.1)
  Downloading cligj-0.7.2-py3-none-any.whl.metadata (5.0 kB)
Downloading geopandas-0.8.1-py2.py3-none-any.whl (962 kB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 962.8/962.8 kB 11.2 MB/s eta 0:00:00
Downloading pandas-3.0.3-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl (10.9 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.9/10.9 MB 32.1 MB/s eta 0:00:00
Downloading pyproj-3.7.2-cp312-cp312-manylinux_2_28_x86_64.whl (9.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 9.6/9.6 MB 50.9 MB/s eta 0:00:00
Downloading fiona-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (17.2 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 17.2/17.2 MB 48.6 MB/s eta 0:00:00
Downloading shapely-2.1.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (3.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.1/3.1 MB 35.2 MB/s eta 0:00:00
Downloading click_plugins-1.1.1.2-py2.py3-none-any.whl (11 kB)
Downloading cligj-0.7.2-py3-none-any.whl (7.1 kB)
Downloading numpy-2.4.4-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (16.6 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 16.6/16.6 MB 48.0 MB/s eta 0:00:00
Installing collected packages: pyproj, numpy, cligj, click-plugins, shapely, pandas, fiona, geopandas
Successfully installed click-plugins-1.1.1.2 cligj-0.7.2 fiona-1.10.1 geopandas-0.8.1 numpy-2.4.4 pandas-3.0.3 pyproj-3.7.2 shapely-2.1.2
Defaulting to user installation because normal site-packages is not writeable
Collecting pyshp==2.1.2
  Downloading pyshp-2.1.2.tar.gz (217 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 217.9/217.9 kB 3.6 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... - done
Building wheels for collected packages: pyshp
  Building wheel for pyshp (setup.py) ... - \ | done
  Created wheel for pyshp: filename=pyshp-2.1.2-py3-none-any.whl size=36262 sha256=de1ada8dcb30b8bd1dda802539bb4a0621e4b8950835afc50819d4f29c846d85
  Stored in directory: /home/runner/.cache/pip/wheels/a6/10/a2/4dd244aa068b6f8af8b6b0917460d22835c34219db822df02f
Successfully built pyshp
Installing collected packages: pyshp
Successfully installed pyshp-2.1.2
Defaulting to user installation because normal site-packages is not writeable
Collecting shapely==1.7.1
  Downloading Shapely-1.7.1.tar.gz (383 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 383.2/383.2 kB 6.2 MB/s eta 0:00:00
  Preparing metadata (setup.py) ... - \ error
  error: subprocess-exited-with-error
  
  × python setup.py egg_info did not run successfully.
   exit code: 1
  ╰─> [13 lines of output]
      Failed `CDLL(libgeos_c.so.1)`
      Failed `CDLL(libgeos_c.so)`
      Traceback (most recent call last):
        File "<string>", line 2, in <module>
        File "<pip-setuptools-caller>", line 34, in <module>
        File "/tmp/pip-install-bxgn3odu/shapely_ae0ce660b0474d1ebdce786d78c4aafd/setup.py", line 85, in <module>
          from shapely._buildcfg import geos_version_string, geos_version, \
        File "/tmp/pip-install-bxgn3odu/shapely_ae0ce660b0474d1ebdce786d78c4aafd/shapely/_buildcfg.py", line 169, in <module>
          lgeos = load_dll('geos_c',
                  ^^^^^^^^^^^^^^^^^^
        File "/tmp/pip-install-bxgn3odu/shapely_ae0ce660b0474d1ebdce786d78c4aafd/shapely/_buildcfg.py", line 162, in load_dll
          raise OSError(
      OSError: Could not find library geos_c or load any of its variants ['libgeos_c.so.1', 'libgeos_c.so']
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: metadata-generation-failed

× Encountered error while generating package metadata.
╰─> See above for output.

note: This is an issue with the package mentioned above, not pip.
hint: See above for details.

If you are using Windows, follow this post to properly install geopandas and dependencies: http://geoffboeing.com/2014/09/using-geopandas-windows/. If you are using Anaconda, do not use PIP to install the packages above. Instead use conda to install them:

conda install plotly conda install geopandas

FIPS and Values

Every US state and county has an assigned ID regulated by the US Federal Government under the term FIPS (Federal Information Processing Standards) codes. There are state codes and county codes: the 2016 state and county FIPS codes can be found at the US Census Website.

Combine a state FIPS code (eg. 06 for California) with a county FIPS code of the state (eg. 059 for Orange county) and this new state-county FIPS code (06059) uniquely refers to the specified state and county.

ff.create_choropleth only needs a list of FIPS codes and a list of values. Each FIPS code points to one county and each corresponding value in values determines the color of the county.

Simple Example

A simple example of this is a choropleth a few counties in California:

In [2]:
import plotly.figure_factory as ff

fips = ['06021', '06023', '06027',
        '06029', '06033', '06059',
        '06047', '06049', '06051',
        '06055', '06061']
values = range(len(fips))

fig = ff.create_choropleth(fips=fips, values=values)
fig.layout.template = None
fig.show()
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:774: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  fips_polygon_map[f].type
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:330: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if fips_polygon_map[f].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:847: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if df_state["geometry"][index].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:852: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif df_state["geometry"][index].type == "MultiPolygon":

Change the Scope

Even if your FIPS values belong to a single state, the scope defaults to the entire United States as displayed in the example above. Changing the scope of the choropleth shifts the zoom and position of the USA map. You can define the scope with a list of state names and the zoom will automatically adjust to include the state outlines of the selected states.

By default scope is set to ['USA'] which the API treats as identical to passing a list of all 50 state names:

['AK', 'AL', 'CA', ...]

State abbreviations (eg. CA) or the proper names (eg. California) as strings are accepted. If the state name is not recognized, the API will throw a Warning and indicate which FIPS values were ignored.

Another param used in the example below is binning_endpoints. If your values is a list of numbers, you can bin your values into half-open intervals on the real line.

In [3]:
import plotly.figure_factory as ff

import numpy as np
import pandas as pd

df_sample = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/minoritymajority.csv')
df_sample_r = df_sample[df_sample['STNAME'] == 'California']

values = df_sample_r['TOT_POP'].tolist()
fips = df_sample_r['FIPS'].tolist()

colorscale = [
    'rgb(193, 193, 193)',
    'rgb(239,239,239)',
    'rgb(195, 196, 222)',
    'rgb(144,148,194)',
    'rgb(101,104,168)',
    'rgb(65, 53, 132)'
]

fig = ff.create_choropleth(
    fips=fips, values=values, scope=['CA', 'AZ', 'Nevada', 'Oregon', ' Idaho'],
    binning_endpoints=[14348, 63983, 134827, 426762, 2081313], colorscale=colorscale,
    county_outline={'color': 'rgb(255,255,255)', 'width': 0.5}, round_legend_values=True,
    legend=dict(
      title=dict(
        text='Population by County'
      )
    ),
    title=dict(
      text='California and Nearby States'
    )
)
fig.layout.template = None
fig.show()
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:808: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  fips_polygon_map[f].type
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:330: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if fips_polygon_map[f].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:357: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif fips_polygon_map[f].type == "MultiPolygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:847: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if df_state["geometry"][index].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:852: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif df_state["geometry"][index].type == "MultiPolygon":

Single State

In [4]:
import plotly.figure_factory as ff

import numpy as np
import pandas as pd

df_sample = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/minoritymajority.csv')
df_sample_r = df_sample[df_sample['STNAME'] == 'Florida']

values = df_sample_r['TOT_POP'].tolist()
fips = df_sample_r['FIPS'].tolist()

endpts = list(np.mgrid[min(values):max(values):4j])
colorscale = ["#030512","#1d1d3b","#323268","#3d4b94","#3e6ab0",
              "#4989bc","#60a7c7","#85c5d3","#b7e0e4","#eafcfd"]
fig = ff.create_choropleth(
    fips=fips, values=values, scope=['Florida'], show_state_data=True,
    colorscale=colorscale, binning_endpoints=endpts, round_legend_values=True,
    plot_bgcolor='rgb(229,229,229)',
    paper_bgcolor='rgb(229,229,229)',
    legend_title='Population by County',
    county_outline={'color': 'rgb(255,255,255)', 'width': 0.5},
    exponent_format=True,
)
fig.layout.template = None
fig.show()
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:808: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  fips_polygon_map[f].type
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:330: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if fips_polygon_map[f].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:357: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif fips_polygon_map[f].type == "MultiPolygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:847: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if df_state["geometry"][index].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:852: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif df_state["geometry"][index].type == "MultiPolygon":

Multiple States

In [5]:
import plotly.figure_factory as ff

import pandas as pd

NE_states = ['Connecticut', 'Maine', 'Massachusetts', 'New Hampshire', 'Rhode Island', 'Vermont']
df_sample = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/minoritymajority.csv')
df_sample_r = df_sample[df_sample['STNAME'].isin(NE_states)]

values = df_sample_r['TOT_POP'].tolist()
fips = df_sample_r['FIPS'].tolist()

colorscale = [
    'rgb(68.0, 1.0, 84.0)',
    'rgb(66.0, 64.0, 134.0)',
    'rgb(38.0, 130.0, 142.0)',
    'rgb(63.0, 188.0, 115.0)',
    'rgb(216.0, 226.0, 25.0)'
]

fig = ff.create_choropleth(
    fips=fips, values=values,
    scope=NE_states, county_outline={'color': 'rgb(255,255,255)', 'width': 0.5},
    legend_title='Population per county'

)
fig.update_layout(
    legend_x = 0,
    annotations = {'x': -0.12, 'xanchor': 'left'}
)

fig.layout.template = None
fig.show()
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:774: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  fips_polygon_map[f].type
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:330: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if fips_polygon_map[f].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:357: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif fips_polygon_map[f].type == "MultiPolygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:847: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if df_state["geometry"][index].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:852: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif df_state["geometry"][index].type == "MultiPolygon":

Simplify County, State Lines

Below is a choropleth that uses several other parameters. For a full list of all available params call help(ff.create_choropleth)

  • simplify_county determines the simplification factor for the counties. The larger the number, the fewer vertices and edges each polygon has. See http://toblerity.org/shapely/manual.html#object.simplify for more information.
  • simplify_state simplifies the state outline polygon. See the documentation for more information. Default for both simplify_county and simplify_state is 0.02

Note: This choropleth uses a divergent categorical colorscale. See http://react-colorscales.getforge.io/ for other cool colorscales.

In [6]:
import plotly.figure_factory as ff

import pandas as pd

scope = ['Oregon']
df_sample = pd.read_csv(
    'https://raw.githubusercontent.com/plotly/datasets/master/minoritymajority.csv'
)
df_sample_r = df_sample[df_sample['STNAME'].isin(scope)]

values = df_sample_r['TOT_POP'].tolist()
fips = df_sample_r['FIPS'].tolist()

colorscale = ["#8dd3c7", "#ffffb3", "#bebada", "#fb8072",
              "#80b1d3", "#fdb462", "#b3de69", "#fccde5",
              "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f",
              "#8dd3c7", "#ffffb3", "#bebada", "#fb8072",
              "#80b1d3", "#fdb462", "#b3de69", "#fccde5",
              "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f",
              "#8dd3c7", "#ffffb3", "#bebada", "#fb8072",
              "#80b1d3", "#fdb462", "#b3de69", "#fccde5",
              "#d9d9d9", "#bc80bd", "#ccebc5", "#ffed6f"]

fig = ff.create_choropleth(
    fips=fips, values=values, scope=scope,
    colorscale=colorscale, round_legend_values=True,
    simplify_county=0, simplify_state=0,
    county_outline={'color': 'rgb(15, 15, 55)', 'width': 0.5},
    state_outline={'width': 1},
    legend_title='pop. per county',
    title='Oregon'
)

fig.layout.template = None
fig.show()
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:774: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  fips_polygon_map[f].type
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:330: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if fips_polygon_map[f].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:357: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif fips_polygon_map[f].type == "MultiPolygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:847: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if df_state["geometry"][index].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:852: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif df_state["geometry"][index].type == "MultiPolygon":

The Entire USA

In [7]:
import plotly.figure_factory as ff

import numpy as np
import pandas as pd

df_sample = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/laucnty16.csv')
df_sample['State FIPS Code'] = df_sample['State FIPS Code'].apply(lambda x: str(x).zfill(2))
df_sample['County FIPS Code'] = df_sample['County FIPS Code'].apply(lambda x: str(x).zfill(3))
df_sample['FIPS'] = df_sample['State FIPS Code'] + df_sample['County FIPS Code']

colorscale = ["#f7fbff","#ebf3fb","#deebf7","#d2e3f3","#c6dbef","#b3d2e9","#9ecae1",
              "#85bcdb","#6baed6","#57a0ce","#4292c6","#3082be","#2171b5","#1361a9",
              "#08519c","#0b4083","#08306b"]
endpts = list(np.linspace(1, 12, len(colorscale) - 1))
fips = df_sample['FIPS'].tolist()
values = df_sample['Unemployment Rate (%)'].tolist()

fig = ff.create_choropleth(
    fips=fips, values=values,
    binning_endpoints=endpts,
    colorscale=colorscale,
    show_state_data=False,
    show_hover=True, centroid_marker={'opacity': 0},
    asp=2.9, title='USA by Unemployment %',
    legend_title='% unemployed'
)

fig.layout.template = None
fig.show()
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:808: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  fips_polygon_map[f].type
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:330: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if fips_polygon_map[f].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:357: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif fips_polygon_map[f].type == "MultiPolygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:847: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  if df_state["geometry"][index].type == "Polygon":
/home/runner/work/plotly.py/plotly.py/doc/.venv/lib/python3.9/site-packages/plotly/figure_factory/_county_choropleth.py:852: ShapelyDeprecationWarning: The 'type' attribute is deprecated, and will be removed in the future. You can use the 'geom_type' attribute instead.
  elif df_state["geometry"][index].type == "MultiPolygon":

Also see tile county choropleths made in Python: https://plotly.com/python/tile-county-choropleth/

Reference

For more info on ff.create_choropleth(), see the full function reference

What About Dash?

Dash is an open-source framework for building analytical applications, with no Javascript required, and it is tightly integrated with the Plotly graphing library.

Learn about how to install Dash at https://dash.plot.ly/installation.

Everywhere in this page that you see fig.show(), you can display the same figure in a Dash application by passing it to the figure argument of the Graph component from the built-in dash_core_components package like this:

import plotly.graph_objects as go # or plotly.express as px
fig = go.Figure() # or any Plotly Express function e.g. px.bar(...)
# fig.add_trace( ... )
# fig.update_layout( ... )

from dash import Dash, dcc, html

app = Dash()
app.layout = html.Div([
    dcc.Graph(figure=fig)
])

app.run(debug=True, use_reloader=False)  # Turn off reloader if inside Jupyter