二进制/一元谓词函数将python中的所有对象与所有其他对象进行交叉比较

时间:2019-07-08 07:04:48

标签: python r gis geopandas sf

我之前曾问过a very similar question。由于arcpy解决方案非常麻烦,因此我现在正在geopandas中寻找基本相同的功能。问题是:应用二进制谓词函数(e.g. touches)最快/最好的方法是什么,其中将x each 功能与其他进行比较x或其他数据集y的em>功能。我期望输出类似于R中的默认行为:

  

如果缺少y,则会有效调用st_predicate(x, x),并返回包含对角元素st_predicate(x[i], x[i])的方阵。

使用一些伪数据和功能st_overlaps()来举例说明:

library(sf)

b0 = st_polygon(list(rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))))
a0 = b0 * 0.8
a1 = a0 * 0.5 + c(2, 0.7)
a2 = a0 + 1
a3 = b0 * 0.5 + c(2, -0.5)
x = st_sfc(a0,a1,a2,a3)

plot(x)

st_overlaps(x)
#> Sparse geometry binary predicate list of length 4, where the predicate was `overlaps'
#>  1: 3
#>  2: 3
#>  3: 1, 2
#>  4: (empty)

如何在python / geopandas中实现类似的行为?显然,geopandas自动对齐xx / y并执行明智的比较(请参阅this SO question和{{ 3}})。在python中,运行x.overlaps(x)只会返回带有四个True值的熊猫系列。

import geopandas as gpd

x.overlaps(x)
0      True
1      True
2      True
3      True

2 个答案:

答案 0 :(得分:1)

这绝对不是最快的方法,因为它只是一个简单的迭代器,但是如果您的数据不是很大,则可以完成工作。

import geopandas as gpd
from shapely.geometry import Polygon

b0 = Polygon([(-1,-1), (1,-1), (1,1), (-1,1)])
a1 = Polygon([(1.5,0.2), (2.5,0.2), (2.5,1.2), (1.5,1.2)])
a2 = Polygon([(0,0), (2,0), (2,2), (0,2)])
a3 = Polygon([(1.5,-1), (2.5,-1), (2.5,-0.2), (1.5,-0.2)])

series = gpd.GeoSeries([b0, a1, a2, a3])

results = {}
for poly in series.iteritems():
    results[poly[0]] = []
    for poly2 in series.drop(poly[0]).iteritems():
        if poly[1].overlaps(poly2[1]):
            results[poly[0]].append(poly2[0])

它将为您提供dict的值。

{0: [2], 1: [2], 2: [0, 1], 3: []}

但是,请注意,它会先检查A-> B,然后再检查B-> A,并且即使多边形距离很远,它也会检查多边形。为了加快速度,您可以使用rtree空间索引仅检查那些可能重叠的对象,而不是将每个多边形相互检查(两次)。

答案 1 :(得分:0)

Python的惯用表达方式是列表理解,例如要创建由元组(索引:(重叠索引))组成的列表,您可以编写

[ ( ind, 
    [ind2 for ind2, g2 in enumerate(series) if g.overlaps(g2)] 
  ) 
  for ind, g in enumerate(series) ]

结果:

[(0, [2]), (1, [2]), (2, [0, 1]), (3, [])]

但是,正如martinfleis所指出的那样,这并不是一种超级有效的方法,因为它不使用任何类型的空间索引。

使用重叠操作可能会获得更好的性能,请参见http://geopandas.org/set_operations.html