Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Geopandas Dataframe Points to Polygons

I have a geopandas dataframe made up of an id and a geometry column which is populated by 2D points. I want to join the points for each unique id to create a polygon, so that my new dataframe will have polygons as its geometry. My code currently looks something like this:

polygons = geopandas.GeoDataFrame() 
for i in id:
    group = df[df['id']== i]
    polygon = {'type': 'Polygon', 'coordinates': group['geometry']}
    polygon['poly'] = polygon
    polygons = geopandas.concat([polygon,polygons])

It creates a polygon but when I assign the new variable poly it says

ValueError: Length of values does not match length of index"

which makes sense since it is still just a list of coordinates and not an actual polygon object. Does anyone know how to make this an actual polygon object that I can add to a column on a geopandas df?
Thanks in advance :)

like image 275
GSam11 Avatar asked Aug 23 '16 15:08

GSam11


People also ask

Does GeoPandas use shapely?

GeoPandas 0.12. GeoPandas is an open source project to make working with geospatial data in python easier. GeoPandas extends the datatypes used by pandas to allow spatial operations on geometric types. Geometric operations are performed by shapely.

Can GeoPandas read shapefile?

You can also read in shapefiles as GeoDataFrames. The code below reads the ecoregions shapefile into a GeoDataFrame after first importing GeoPandas.

Can a GeoDataFrame have two geometry columns?

A GeoDataFrame may also contain other columns with geometrical (shapely) objects, but only one column can be the active geometry at a time.


2 Answers

I have achieved something similar with the groupby function. Assuming your points are actually Shapely Point objects, and are sorted in the right order, you can try something like this.

import pandas as pd
import geopandas as gp
from shapely.geometry import Point, Polygon

# Initialize a test GeoDataFrame where geometry is a list of points
df = gp.GeoDataFrame( [['box', Point(1, 0)], 
                       ['box', Point(1, 1)], 
                       ['box', Point(2,2)], 
                       ['box', Point(1,2)], 
                       ['triangle', Point(1, 1)], 
                       ['triangle', Point(2,2)], 
                       ['triangle', Point(3,1)]],  
                     columns = ['shape_id', 'geometry'], 
                     geometry='geometry')

# Extract the coordinates from the Point object
df['geometry'] = df['geometry'].apply(lambda x: x.coords[0])

# Group by shape ID 
#  1. Get all of the coordinates for that ID as a list
#  2. Convert that list to a Polygon
df = df.groupby('shape_id')['geometry'].apply(lambda x: Polygon(x.tolist())).reset_index()

# Declare the result as a new a GeoDataFrame
df = gp.GeoDataFrame(df, geometry = 'geometry')

df.plot()

enter image description here

like image 193
atkat12 Avatar answered Sep 25 '22 23:09

atkat12


Great answer @atkat12. But according to your plot, last two box points should be (0,1) and (0,0):

   # Initialize a test GeoDataFrame where geometry is a list of points 
   df = gp.GeoDataFrame( [['box', Point(1, 0)], 
                   ['box', Point(1, 1)], 
                   ['box', Point(0,1)], 
                   ['box', Point(0,0)], 
                   ['triangle', Point(1, 1)], 
                   ['triangle', Point(2,2)], 
                   ['triangle', Point(3,1)]],  
                 columns = ['shape_id', 'geometry'], 
                 geometry='geometry')
like image 28
DataK Avatar answered Sep 22 '22 23:09

DataK