I have a pandas dataframe that contains bounding box information for tiled raster data in the following format.

left            bottom              right           top
466583.40921    3135701.9763599997  466586.39673    3135704.9638799997
466583.40921    3135698.98884       466586.39673    3135701.9763599997
466583.40921    3135696.0013200007  466586.39673    3135698.98884
466583.40921    3135693.013800001   466586.39673    3135696.0013200007

Ultimately, I am looking to create a geopandas geodataframe that has a geometry column with the bounding box information in the following format:

POLYGON ((466586.39673 3135701.97636, 466586.39673 3135704.96388, 466583.40921 3135704.96388, 466583.40921 3135701.97636, 466586.39673 3135701.97636))
POLYGON ((466586.39673 3135698.98884, 466586.39673 3135701.97636, 466583.40921 3135701.97636, 466583.40921 3135698.98884, 466586.39673 3135698.98884))
...and so on...

I am aware that I can create a POLYGON object using the box method and referencing a single row:

box(df.left[1], df.bottom[1], df.right[1], df.top[1])

I have also tried hacking together a solution from a similar question:

b = [x for x in box(df.left, df.bottom, df.right, df.top)]

Which yields the following error:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

How can I convert shapely bounding data as in the first dataframe to a geopandas geodataframe as in the second dataframe above?

2 Answers 2


A full solution including imports:

from shapely.geometry import box
from geopandas import GeoDataFrame
import pandas as pd

INIT_PATH = './data.csv'
df = pd.read_csv(INIT_PATH, sep='\t')
geometry = [box(x1, y1, x2, y2) for x1,y1,x2,y2 in zip(df.left, df.bottom, df.right, df.top)]
df = df.drop(['left', 'bottom', 'right', 'top'], axis=1)
geodf = GeoDataFrame(df, geometry=geometry)



0  POLYGON ((466586.397 3135701.976, 466586.397 3...
1  POLYGON ((466586.397 3135698.989, 466586.397 3...
2  POLYGON ((466586.397 3135696.001, 466586.397 3...
3  POLYGON ((466586.397 3135693.014, 466586.397 3...

You are almost there with what you tried, and using the box method is indeed the best way. With the list comprehension, you can do

b = [box(l, b, r, t) for l, b, r, t in zip(df.left, df.bottom, df.right, df.top)]

Another option is to apply the box function to each row of your dataframe:

b = df.apply(lambda row: box(row.left, row.bottom, row.right, row.top), axis=1)

Once you have converted the bounding boxes to polygons, make sure to actually create a GeoDataFrame:

gdf = geopandas.GeoDataFrame(df, geometry=b)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.