Asif Marazi
Asif Marazi

Reputation: 137

Clipping shapefile with multi-polygon shapefile in geopandas

I have a shapefile (will be called source-file hereafter), which I need to clip by a multi-polygon shapefile so that I can have a clipped shapefile for each polygon. I tried the geopandas, though I am able to clip the source-file by individually clipping the it by selecting the polygons separately from the multi-polygon shapefile, but when I try to loop over the polygons to automate the clipping process I get the following error:

Error: TypeError: 'mask' should be GeoDataFrame, GeoSeries or(Multi)Polygon, got <class 'tuple'>

Code:

import geopandas as gpd

source = ('source-shapefile.shp')
mask = ('mask_shapefile.shp')
sourcefile = gpd.read_file(source)
maskfile = gpd.read_file(mask)
for row in maskfile.iterrows():
    gpd.clip(sourcefile, row)

Upvotes: 2

Views: 1931

Answers (2)

Asif Marazi
Asif Marazi

Reputation: 137

Finally, after 5 hours of research, I am now able clip the shapefile by a multi-polygon shapefile and save the clipped polygons separately with their respective names. Following code may be dirty but it works. code:

import geopandas as gpd
import pandas as pd
import os, sys

source = ('source-shapefile.shp')
mask = ('mask_shapefile.shp')
outpath = ('/outpath')

sourcefile = gpd.read_file(source)
maskfile = gpd.read_file(mask)

clipshape = maskfile.explode()

clipshape.set_index('CATCH_NAME', inplace=True) # CATCH_NAME is attribute column name

for index, row in clipshape['geometry'].iteritems():
    clipped = gpd.clip(sourcefile, row)
    clipped.to_file(os.path.join(outpath, f'{index}.shp'))

Upvotes: 1

Rob Raymond
Rob Raymond

Reputation: 31156

Two points

Have constructed an example. It is far simpler to clip using a GeoDataFrame as the mask.

import geopandas as gpd
import pandas as pd

# lets build a mask for use in clip, multipolygons and polygons
maskfile = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))
maskfile = maskfile.loc[maskfile["continent"].eq("Europe") & maskfile["name"].ne("Russia")].pipe(
    lambda d: d.assign(gdp_grp=pd.cut(d["gdp_md_est"], bins=4, labels=list("abcd")))
).dissolve("gdp_grp").reset_index()

sourcefile = gpd.read_file(gpd.datasets.get_path("naturalearth_lowres"))

# now clip, no looping needed
gpd.clip(sourcefile, maskfile)

Upvotes: 2

Related Questions