Python 识别Geopandas/Shapely中多边形的唯一分组

Python 识别Geopandas/Shapely中多边形的唯一分组,python,geopandas,shapely,Python,Geopandas,Shapely,假设我有两个不相交的多边形群/“岛”(想想两个不相邻县的人口普查区)。我的数据可能如下所示: >>> p1=Polygon([(0,0),(10,0),(10,10),(0,10)]) >>> p2=Polygon([(10,10),(20,10),(20,20),(10,20)]) >>> p3=Polygon([(10,10),(10,20),(0,10)]) >>> >>> p4=Polygon([

假设我有两个不相交的多边形群/“岛”(想想两个不相邻县的人口普查区)。我的数据可能如下所示:

>>> p1=Polygon([(0,0),(10,0),(10,10),(0,10)])
>>> p2=Polygon([(10,10),(20,10),(20,20),(10,20)])
>>> p3=Polygon([(10,10),(10,20),(0,10)])
>>> 
>>> p4=Polygon([(40,40),(50,40),(50,30),(40,30)])
>>> p5=Polygon([(40,40),(50,40),(50,50),(40,50)])
>>> p6=Polygon([(40,40),(40,50),(30,50)])
>>> 
>>> df=gpd.GeoDataFrame(geometry=[p1,p2,p3,p4,p5,p6])
>>> df
                                        geometry
0        POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))
1  POLYGON ((10 10, 20 10, 20 20, 10 20, 10 10))
2          POLYGON ((10 10, 10 20, 0 10, 10 10))
3  POLYGON ((40 40, 50 40, 50 30, 40 30, 40 40))
4  POLYGON ((40 40, 50 40, 50 50, 40 50, 40 40))
5         POLYGON ((40 40, 40 50, 30 50, 40 40))
>>> 
>>> df.plot()

我希望每个岛内的多边形采用表示其组的ID(可以是任意的)。例如,左下角的3个多边形的IslandID为1,右上角的3个多边形的IslandID为2

我已经找到了一种方法,但我想知道这是否是最好/最有效的方法。我做了以下工作:

1) 创建一个几何体等于多多边形一元并集内多边形的地理数据框。这给了我两个多边形,每个“岛”一个

2) 为每个组创建一个ID

>>> SepIslands['IslandID']=SepIslands.index+1
3) 在空间上将孤岛连接到原始多边形,以便每个多边形都具有相应的孤岛id

>>> Final=gpd.tools.sjoin(df, SepIslands, how='left').drop('index_right',1)
>>> Final
                                        geometry  IslandID
0        POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))         1
1  POLYGON ((10 10, 20 10, 20 20, 10 20, 10 10))         1
2          POLYGON ((10 10, 10 20, 0 10, 10 10))         1
3  POLYGON ((40 40, 50 40, 50 30, 40 30, 40 40))         2
4  POLYGON ((40 40, 50 40, 50 50, 40 50, 40 40))         2
5         POLYGON ((40 40, 40 50, 30 50, 40 40))         2

这真的是最好/最有效的方法吗

如果每组之间的间距相当大,另一种选择是将多边形的质心聚类并将其标记为簇

DBSCAN代表有噪声的应用程序的基于密度的空间聚类,它可以将紧密排列在一起的点分组。在我们的例子中,一个岛上的多边形将聚集在同一个簇中

这也适用于两个以上的岛屿

将geopandas导入为gpd
作为pd进口熊猫
从shapely.geometry导入多边形
从sklearn.cluster导入DBSCAN
#注意,EPS_DISTANCE=20是一个神奇的数字,需要
#*小于任何两个岛屿之间的间隙
#*足够大,可以将多边形聚集在同一簇中的一个岛上
EPS_距离=20
最小采样多边形=1
p1=多边形([(0,0)、(10,0)、(10,10)、(0,10)])
p2=多边形([(10,10)、(20,10)、(20,20)、(10,20)])
p3=多边形([(10,10)、(10,20)、(0,10)])
p4=多边形([(40,40),(50,40),(50,30),(40,30)])
p5=多边形([(40,40),(50,40),(50,50),(40,50)])
p6=多边形([(40,40)、(40,50)、(30,50)])
df=gpd.GeoDataFrame(几何图形=[p1,p2,p3,p4,p5,p6])
#dbscan的准备
df['x']=df['geometry'].形心.x
df['y']=df['geometry'].形心.y
coords=df.as_矩阵(列=['x','y'])
#dbscan
dbscan=dbscan(eps=eps\U距离,最小采样数=最小采样数\U多边形)
集群=dbscan.fit(coords)
#将标签添加回数据帧
labels=pd.Series(clusters.labels)。重命名('IslandID')
df=pd.concat([df,标签],轴=1)

对我来说似乎是一种合乎逻辑的方法。最后一步的替代方案可能是在中使用
,以检查每个对象位于哪个组合多边形内,但我认为与连接方法相比,这将变得更加复杂。很好的解决方案!但是
df。由于不推荐使用矩阵
,现在最好使用:
coords=df[[“x”,“y”]]
>>> Final=gpd.tools.sjoin(df, SepIslands, how='left').drop('index_right',1)
>>> Final
                                        geometry  IslandID
0        POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))         1
1  POLYGON ((10 10, 20 10, 20 20, 10 20, 10 10))         1
2          POLYGON ((10 10, 10 20, 0 10, 10 10))         1
3  POLYGON ((40 40, 50 40, 50 30, 40 30, 40 40))         2
4  POLYGON ((40 40, 50 40, 50 50, 40 50, 40 40))         2
5         POLYGON ((40 40, 40 50, 30 50, 40 40))         2
> df
                                        geometry  ...  IslandID
0        POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))  ...         0
1  POLYGON ((10 10, 20 10, 20 20, 10 20, 10 10))  ...         0
2          POLYGON ((10 10, 10 20, 0 10, 10 10))  ...         0
3  POLYGON ((40 40, 50 40, 50 30, 40 30, 40 40))  ...         1
4  POLYGON ((40 40, 50 40, 50 50, 40 50, 40 40))  ...         1
5         POLYGON ((40 40, 40 50, 30 50, 40 40))  ...         1
[6 rows x 4 columns]