How to fix the Geopandas error 'GeoSeries' or 'GeoDataFrame' object has no attribute 'geoms' ?


Introduction

If you are working with geospatial data, chances are you have encountered the GeoSeries or GeoDataFrame object error at some point. This is a common issue that many people face when using these objects in Python.

First, it's important to understand why this error occurs. The GeoSeries and GeoDataFrame objects are part of the popular geospatial library - GeoPandas. These objects contain various geometric data structures, such as points, lines, and polygons.

When we encounter the 'GeoSeries' or 'GeoDataFrame' object has no attribute 'geoms' error, it means that we are trying to access a geometric attribute that does not exist in our data.

Most frequent reason why this error might occur

There can be several reasons why this error might occur. The most frequent reason is attempting to apply geoms to GeoSeries or GeoDataFrame objects instead of a shapely geometry multipolygon. For example, when executing the code

my_variable.geoms

, the resulting output is...

AttributeError: 'GeoSeries' object has no attribute 'geoms'

or

AttributeError: 'GeoDataFrame' object has no attribute 'geoms'

Please attempt:

type(my_variable)

you should get

geopandas.geoseries.GeoSeries

or

geopandas.geodataframe.GeoDataFrame

How to Fix It

To resolve the issue, it is usually straightforward. Firstly, you need to extract the multipolygon from the GeoSeries or GeoDataFrame.

my_variable.iloc[0]

check the type

type(my_variable.iloc[0])

should give

shapely.geometry.multipolygon.MultiPolygon

and then apply geoms

my_variable.iloc[0].geoms

Example of case

Allow me to present an example where I encountered an error message for the first time and provide you with a solution to resolve it.

Let's consider the following geopandas dataframe

import pandas as pd
import geopandas as gpd

df = pd.DataFrame(
    {
        "City": ["Paris", "New-York", "London", "Marseille", "Dijon", "Bordeaux"],
        "Latitude": [48.8566, 40.7128, 51.5072, 43.2965, 47.3220, 44.8378],
        "Longitude": [2.3522, -74.0060, -0.1276, 5.3698, 5.0415, -0.5792],
    }
)

gdf = gpd.GeoDataFrame(
    df, geometry=gpd.points_from_xy(df.Longitude, df.Latitude), crs="EPSG:4326"
)

gives

        City  Latitude  Longitude                    geometry
0      Paris   48.8566     2.3522    POINT (2.35220 48.85660)
1   New-York   40.7128   -74.0060  POINT (-74.00600 40.71280)
2     London   51.5072    -0.1276   POINT (-0.12760 51.50720)
3  Marseille   43.2965     5.3698    POINT (5.36980 43.29650)
4      Dijon   47.3220     5.0415    POINT (5.04150 47.32200)
5   Bordeaux   44.8378    -0.5792   POINT (-0.57920 44.83780)

Our goal is to narrow down this dataframe to include only cities located in France. We will be using a polygon of France to filter the cities that fall within its boundaries (see previous article How to filter a geopandas dataframe for points that fall within a specified polygon ?).

Extract France Geometries using Natural Earth Data (see How to retrieve country name for a given latitude and longitude using geopandas and naturalearthdata ? ):

df_110m_cultural = gpd.read_file('110m_cultural')

df_110m_cultural[ df_110m_cultural[ 'ADMIN' ] == 'France' ]

Now if we try

df_110m_cultural[ df_110m_cultural[ 'ADMIN' ] == 'France' ]['geometry'].geoms

we will get

AttributeError: 'GeoSeries' object has no attribute 'geoms'

since

type(df_110m_cultural[ df_110m_cultural[ 'ADMIN' ] == 'France' ]['geometry'])

returns

geopandas.geoseries.GeoSeries

How to fix it:

fr_geometries = df_110m_cultural['geometry'][ df_110m_cultural[ 'ADMIN' ] == 'France' ]

len(fr_geometries.iloc[0])

Output

3

And

type(fr_geometries.iloc[0])

Output

shapely.geometry.multipolygon.MultiPolygon

Extract France geometries

geoms = [g for g in fr_geometries.iloc[0].geoms]

France Metropolitan:

gdf.within( geoms[1] )

Output

0     True
1    False
2    False
3     True
4     True
5     True
dtype: bool

References