Search code examples
pythonplotlygeopandaschoropleth

How to use plotly with geodataframe geometry


I want to plot a geojson/geometry map with plotly sliders (for time). Here's what my gdf looks like:

gdf.head()
                                            
|     |  key  |  value  | geometry                                            |
| --- | ----- | ------- | --------------------------------------------------- |
|  0  | key1  | 33.094  | MULTIPOLYGON (((-93.50080 38.17240, -93.49680 ...   |
|  1  | key2  | 33.833  | MULTIPOLYGON (((-114.06920 48.99950, -114.0644...   |
|  2  | key3  | 30.000  | MULTIPOLYGON (((-118.83760 49.00000, -118.8360...   |
|  3  | key4  | 29.010  | MULTIPOLYGON (((-110.58290 32.04520, -110.4543...   |

(where key are strings)

and I have several files for different years and months that has different values correspond to key/geometry pair. I want to plot something so I have a time slider and can easily visualize the value change of each region along the time. I see plotly could potentially do this (link) , and this is what I want, but I'm not able to get there:

example plot

In plotly, one way to take advantage of slider is to use fig.add_trace() and add plotly plots to it. So I'm trying to use the example code on plotly for px.choropleth() but still not able to show my polygons.

I also did gdf.explode(ignore_index=True) to explode 'geometry' from MULTIPLOLYGON to POLYGON, but still nothing changed.

overall the code looks like this:

gdf = geopandas.read_file(file_path)
gdf = gdf.explode(ignore_index=True)

fig = px.choropleth(
    gdf,
    geojson=gdf.geometry,
    color='value',
    scope="north america",
    locations=gdf.key
)
fig.show()

and the plot like this: plot with px.choropleth

While if I directly use gdf.plot() either explode or not, I got this: plot with geopandas

Any help would be appreciated!


Solution

  • Since the question did not have sample data, I used the data in the reference and expanded it to the five-year district-by-district polling results. Now the data is ready for the animated slider. I also set up a CRS for the json in the reference as geometry and loaded it as a geopandas data frame. The geojson specification in my map creation code is using an interface that converts from the geopandas data frame I just created to geojson. Please replace the key column in the question with the district column in my answer.

    import plotly.express as px
    import geopandas as gpd
    import pandas as pd
    import numpy as np
    
    df = px.data.election()
    
    dff = pd.DataFrame({'district': df['district'].tolist()*5,#np.repeat(df['district'],5),
                        'total': np.random.randint(5000,12000,len(df)*5),
                        'year': sum([[x]*len(df) for x in np.arange(2017, 2022,1)],[])
                       })
    
    geojson = px.data.election_geojson()
    gdf = gpd.GeoDataFrame.from_features(geojson,  crs='epsg:4326')
    
    fig = px.choropleth(dff,
                        geojson=gdf.__geo_interface__,
                        color="total",
                        animation_frame='year',
                        locations="district",
                        featureidkey="properties.district",
                        projection="mercator",
                        color_continuous_scale="deep"
                       )
    fig.update_geos(fitbounds="locations", visible=False)
    fig.update_layout(height=500,width=500)
    
    fig.show()
    

    enter image description here