Python 在GeoDataFrame中查找不重叠的多边形

Python 在GeoDataFrame中查找不重叠的多边形,python,shapely,geopandas,Python,Shapely,Geopandas,我有一个GeoDataFrame,其中有一列shapely.polygons。其中一些是不同的,一些是不一样的: In [1]: gdf Out[2]: geometry 1 POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1)) 2 POLYGON ((1 3, 1 4, 2 4, 2 3, 1 3)) 3 POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1)) 4 POLYGON ((3 1, 3 2, 4 2, 4 1, 3 1))

我有一个GeoDataFrame,其中有一列shapely.polygons。其中一些是不同的,一些是不一样的:

In [1]: gdf
Out[2]:
    geometry
1   POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))
2   POLYGON ((1 3, 1 4, 2 4, 2 3, 1 3))
3   POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))
4   POLYGON ((3 1, 3 2, 4 2, 4 1, 3 1))
5   POLYGON ((1 3, 1 4, 2 4, 2 3, 1 3))
我只需要找到不同的(非重叠)多边形:

In [1]: gdf_distinct
Out[2]:
    geometry
1   POLYGON ((1 1, 1 2, 2 2, 2 1, 1 1))
2   POLYGON ((1 3, 1 4, 2 4, 2 3, 1 3))
4   POLYGON ((3 1, 3 2, 4 2, 4 1, 3 1))
由于多边形是不可散列的,我不能在Pandas中使用简单的方法:

In [1]: gdf_distinct = gdf['geometry'].unique()

TypeError: unhashable type: 'Polygon'
有没有简单有效的方法来创建一个只包含不同多边形的新GeoDataFrame

附言:

我找到了一种方法,但它只适用于完全重复的多边形,而且,正如我所认为的,效率不高:

In [1]: m = []
        for index, row in gdf.iterrows():]
           if row['geometry'] not in m:
              m.append(row['geometry'])
        gdf_distinct = GeoDataFrame(geometry=m)

让我们从4个多边形的列表开始,其中3个与其他多边形重叠:

from shapely.geometry import Polygon
import geopandas

polygons = [
    Polygon([[1, 1], [1, 3], [3, 3], [3, 1], [1, 1]]),
    Polygon([[1, 3], [1, 5], [3, 5], [3, 3], [1, 3]]),
    Polygon([[2, 2], [2, 3.5], [3.5, 3.5], [3.5, 2], [2, 2]]),
    Polygon([[3, 1], [3, 2], [4, 2], [4, 1], [3, 1]]),
]
gdf = geopandas.GeoDataFrame(data={'A': list('ABCD')}, geometry=polygons)
gdf.plot(column='A', alpha=0.75)
它们看起来像这样:

所以我们可以遍历每一个,然后遍历所有其他的,并检查与
shapely
API的重叠。如果没有任何重叠,我们将其附加到输出列表中:

non_overlapping = []
for p in polygons:
    overlaps = []
    for g in filter(lambda g: not g.equals(p), polygons):
        overlaps.append(g.overlaps(p))

    if not any(overlaps):
        non_overlapping.append(p)
任何让我感到:

['POLYGON ((3 1, 3 2, 4 2, 4 1, 3 1))']
这正是我所期望的

但这实际上是O(N^2),我认为它不必是

因此,让我们尽量不要对同一对进行两次检查:

non_overlapping = []
for n, p in enumerate(polygons[:-1], 1):  # don't include the last element
    overlaps = []
    for g in polygons[n:]:  # loop from the next element to the end
        overlaps.append(g.overlaps(p))

    if not any(overlaps):
        non_overlapping.append(str(p))
我得到了同样的结果,在我的机器上速度快了一点

我们可以使用
if
语句中的生成器,而不是
for
块中的正常
,将循环压缩一点:

non_overlapping = []
for n, p in enumerate(polygons[:-1], 1):
    if not any(p.overlaps(g) for g in polygons[n:]):
        non_overlapping.append(p)

同样的故事。

首先,我尝试了df.polygon_colu.unique()-但没有成功,因为多边形是不可散列的。现在我正在研究intersects(),当我遍历所有行以检查列中的任何多边形是否与指定的多边形相交时,这似乎不是最好的方法。请编辑我们的问题,以包含您尝试过的代码。格式良好的多边形更有可能吸引答案。进行了一些编辑-希望它能清除这种情况。您想要唯一的多边形,还是不重叠的多边形?因为这不一定是相同的?在我的例子中,我希望有不重叠的多边形(仅仅因为我的数据可能是脏的),感谢您的精彩解释和示例!