Search code examples
pythonplotly

Create plotly graph object for census data


I am trying to plot US census data using plotly. I am able to create a plotly map but its not working for plotly graph object. Below is what I tried:

import numpy as np
import pandas as pd
import censusdata as cd
import geopandas as gpd
import plotly.express as px
from plotly import graph_objs as go

#download census data using censusdata library
df = cd.download('acs5', 2020, cd.censusgeo([('state', '36'), ('county', '*'), ('tract', '*')]), ['B01003_001E'])
df.columns = ['TOTAL_POPULATION']

# fix index
new_indices = []
for index in df.index.tolist():
    new_index = index.geo[0][1] + index.geo[1][1] + index.geo[2][1]
    new_indices.append(new_index)
df['GEOID'] = new_indices
df = df.reset_index(drop=True)
df.head()

# merge with shape file of NY state
path = "shape_files/unzipped/tl_2020_36_tract.shp"
plot = gpd.read_file(path)
plot.plot()
df = pd.merge(df, plot, on='GEOID', how='inner')

# filter data for NY county and plot it using plotly
ny = df[df['COUNTYFP'].isin(['061'])]
geo_df = gpd.GeoDataFrame(ny).set_index("GEOID")
fig = px.choropleth_mapbox(geo_df,
                           geojson=geo_df.geometry,
                           locations=geo_df.index,
                           color="TOTAL_POPULATION", color_continuous_scale=px.colors.sequential.Greens,
                           center={"lat": 40.8, "lon": -73.97},
                           mapbox_style="open-street-map",
                           zoom=11)
fig.update_layout(
    autosize=False,
    width=1000,
    height=1000,
    margin={"r":0,"t":0,"l":0,"b":0}
)
fig.show()

The above code works fine and produces below plot: enter image description here But when I try to plot it using plotly graph object:

fig = go.Figure(go.Choroplethmapbox(geojson=geo_df.geometry, locations=geo_df.index, z=geo_df.TOTAL_POPULATION,
                                    colorscale="Viridis", zmin=0, zmax=12,
                                    marker_opacity=0.5, marker_line_width=0))
fig.update_layout(mapbox_style="carto-positron",
                  mapbox_zoom=3, mapbox_center = {"lat": 37.0902, "lon": -95.7129})
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()

It throws this error:

TypeError: Object of type Polygon is not JSON serializable

How can I fix it and create a plotly graph object?

P.S, you can download shape files from here


Solution

  • The geodata needed by the graph object must be in geojson format, so the geodata frame interface is used to create a dictionary format. I have created the same content in my graph object code as the map you created in Express.

    fig = go.Figure(go.Choroplethmapbox(
        geojson=geo_df.__geo_interface__,
        locations=geo_df.index,
        z=geo_df.TOTAL_POPULATION,
        colorscale="Greens",
        zmin=0, 
        zmax=10000,
        marker_opacity=0.8,
        marker_line_width=1
        )
    )
    fig.update_layout(autosize=False,
                      width=1000,
                      height=1000,
                      mapbox_style="open-street-map",
                      mapbox_zoom=11,
                      mapbox_center = {"lat": 40.8, "lon": -73.97})
    fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
    fig.show()
    

    enter image description here