Search code examples
geopandas

Center of geopandas.geodataframe.GeoDataFrame


The code below renders a map of Census Tracts in San Francisco County. Note that it hard-codes the center of the map:

import plotly.express as px
import censusdis.data as ced
from censusdis.datasets import ACS5

variable = 'B01001_001E' 

df = ced.download(
    dataset=ACS5,
    vintage=2022,         
    download_variables=['NAME', variable], 
    state='06',
    county='075',
    tract='*',
    with_geometry=True)

df = df.set_index('NAME')
df = df.dropna()

fig = px.choropleth_mapbox(df, 
                           geojson=df.geometry,
                           locations=df.index, 
                           center={'lat': 37.74180915, 'lon': -122.38474831884692}, 
                           color=variable, 
                           color_continuous_scale="Viridis", 
                           mapbox_style="carto-positron", 
                           opacity=0.5,
                           zoom=10)
fig.update_layout(margin={"r":0,"t":0,"l":0,"b":0})
fig.show()

I would like to programmatically create maps like this for every county in the country. To do this, however, I need to be able to derive the center of df (which is an object of type geopandas.geodataframe.GeoDataFrame). I am unsure how to do this.

I am aware that the class has a member variable .centroid. But when I call it:

  • It returns an object of type geopandas.geoseries.GeoSeries which seems to be the center of each Tract. But I need a single center point for all tracts.
  • it gives me the warning Geometry is in a geographic CRS. Results from 'centroid' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation. So even if I solve the first point, it appears that I would still need to do an additional step.

How can I get the center of all tracts in the county?


Solution

  • If I understand correctly, you are looking for geopandas.total_bounds. This property returns the minimum bounding box for the entire GeoDataFrame.

    To get the center of it, you can use e.g. shapely.centroid. E.g. something like this:

    import geopandas as gpd
    import shapely
    
    p1 = shapely.Polygon([[0, 0], [0, 1], [1, 1], [0, 0]])
    p2 = shapely.Polygon([[99, 99], [99, 100], [100, 100], [99, 99]])
    df = gpd.GeoDataFrame(data={"desc": ["p1", "p2"]}, geometry=[p1, p2])
    
    center = shapely.box(*df.total_bounds).centroid
    print(center)
    # POINT (50 50)