How to create polygon from bbox data in python?
Question:
I have created a code in R which extracts bbox
from a list of points and then creates a polygon using st_as_sfc
. Now I am trying to do the same in python where I was able to get the bbox
coordinates from the list of points data and then tried to create polygon using the two points by help of shapely.geometry
which is throwing error. Is there any alternative for st_as_sfc
in python or how can I create a polygon from the obtained bbox
coordinates?
R code:-
print(st_as_sfc(st_bbox(sgrid)))
result:-
Geometry set for 1 feature
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -9574057 ymin: 3590448 xmax: -9494057 ymax: 3670448
Projected CRS: WGS 84 / Pseudo-Mercator
POLYGON ((-9574057 3590448, -9494057 3590448, -...
Python :-
data frame from bbox coordinates xmin,ymin and xmax,ymax
from shapely import geometry
print(df)
x y geometry
0 3.418932e+06 -2.088506e+07 POINT (-20885056.99629 3418931.63321)
1 3.478932e+06 -2.082506e+07 POINT (-20825056.99629 3478931.63321)
poly = geometry.Polygon([[p.x, p.y] for p in gdf_p['geometry'].tolist()])
print(poly.wkt)
error:-
ValueError: A linearring requires at least 4 coordinates.
Answers:
No need to first produce point geometries from your coordinates. Simply provide all 4 corners like so:
poly = geometry.Polygon(((xmin,ymin), (xmin,ymax), (xmax,ymax), (xmax,ymin)))
If you already have a dataframe, you can achieve this through unary_union
& envelope
:
import pandas as pd
import geopandas as gpd
from io import StringIO
points = '''geometry
POINT (-20885056.99629 3418931.63321)
POINT (-20825056.99629 3478931.63321)'''
df = pd.read_table(StringIO(points))
gdf = gpd.GeoDataFrame(geometry=gpd.GeoSeries.from_wkt(df['geometry']))
print(gdf)
# geometry
# 0 POINT (-20885056.996 3418931.633)
# 1 POINT (-20825056.996 3478931.633)
print(gdf.geometry.unary_union.envelope.wkt)
# POLYGON ((-20885056.99629 3418931.63321, -20825056.99629 3418931.63321, -20825056.99629 3478931.63321, -20885056.99629 3478931.63321, -20885056.99629 3418931.63321))
With (minx, miny, maxx, maxy)
tuples you can use shapely.geometry.box()
:
from shapely import geometry
bbox_tuple = gdf.total_bounds
print(bbox_tuple)
# [-20885056.99629 3418931.63321 -20825056.99629 3478931.63321]
bbox_polygon = geometry.box(*bbox_tuple)
print(bbox_polygon.wkt)
# POLYGON ((-20825056.99629 3418931.63321, -20825056.99629 3478931.63321, -20885056.99629 3478931.63321, -20885056.99629 3418931.63321, -20825056.99629 3418931.63321))
I have created a code in R which extracts bbox
from a list of points and then creates a polygon using st_as_sfc
. Now I am trying to do the same in python where I was able to get the bbox
coordinates from the list of points data and then tried to create polygon using the two points by help of shapely.geometry
which is throwing error. Is there any alternative for st_as_sfc
in python or how can I create a polygon from the obtained bbox
coordinates?
R code:-
print(st_as_sfc(st_bbox(sgrid)))
result:-
Geometry set for 1 feature
Geometry type: POLYGON
Dimension: XY
Bounding box: xmin: -9574057 ymin: 3590448 xmax: -9494057 ymax: 3670448
Projected CRS: WGS 84 / Pseudo-Mercator
POLYGON ((-9574057 3590448, -9494057 3590448, -...
Python :-
data frame from bbox coordinates xmin,ymin and xmax,ymax
from shapely import geometry
print(df)
x y geometry
0 3.418932e+06 -2.088506e+07 POINT (-20885056.99629 3418931.63321)
1 3.478932e+06 -2.082506e+07 POINT (-20825056.99629 3478931.63321)
poly = geometry.Polygon([[p.x, p.y] for p in gdf_p['geometry'].tolist()])
print(poly.wkt)
error:-
ValueError: A linearring requires at least 4 coordinates.
No need to first produce point geometries from your coordinates. Simply provide all 4 corners like so:
poly = geometry.Polygon(((xmin,ymin), (xmin,ymax), (xmax,ymax), (xmax,ymin)))
If you already have a dataframe, you can achieve this through unary_union
& envelope
:
import pandas as pd
import geopandas as gpd
from io import StringIO
points = '''geometry
POINT (-20885056.99629 3418931.63321)
POINT (-20825056.99629 3478931.63321)'''
df = pd.read_table(StringIO(points))
gdf = gpd.GeoDataFrame(geometry=gpd.GeoSeries.from_wkt(df['geometry']))
print(gdf)
# geometry
# 0 POINT (-20885056.996 3418931.633)
# 1 POINT (-20825056.996 3478931.633)
print(gdf.geometry.unary_union.envelope.wkt)
# POLYGON ((-20885056.99629 3418931.63321, -20825056.99629 3418931.63321, -20825056.99629 3478931.63321, -20885056.99629 3478931.63321, -20885056.99629 3418931.63321))
With (minx, miny, maxx, maxy)
tuples you can use shapely.geometry.box()
:
from shapely import geometry
bbox_tuple = gdf.total_bounds
print(bbox_tuple)
# [-20885056.99629 3418931.63321 -20825056.99629 3478931.63321]
bbox_polygon = geometry.box(*bbox_tuple)
print(bbox_polygon.wkt)
# POLYGON ((-20825056.99629 3418931.63321, -20825056.99629 3478931.63321, -20885056.99629 3478931.63321, -20885056.99629 3418931.63321, -20825056.99629 3418931.63321))