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: 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
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()