Algorithm 如何加速geopandas空间连接?

Algorithm 如何加速geopandas空间连接?,algorithm,join,geopandas,Algorithm,Join,Geopandas,我有两个geopandas数据帧。对于左帧中的每一行,我想找出右帧中的哪些行在空间上与该行重叠,以及重叠程度。一旦我有了这些信息,我就可以根据重叠的程度进行空间连接 不幸的是,我正在对大量多边形进行此操作:一个州内的所有美国人口普查区(德克萨斯州有5265个)和大量大小类似(但不与美国人口普查区一致)的多边形(德克萨斯州有914231个) 我正在寻找一种更快的方法。我的代码如下 使用的数据集可从美国人口普查中获得: #/usr/bin/env蟒蛇3 作为gpd导入geopandas 将geopa

我有两个geopandas数据帧。对于左帧中的每一行,我想找出右帧中的哪些行在空间上与该行重叠,以及重叠程度。一旦我有了这些信息,我就可以根据重叠的程度进行空间连接

不幸的是,我正在对大量多边形进行此操作:一个州内的所有美国人口普查区(德克萨斯州有5265个)和大量大小类似(但不与美国人口普查区一致)的多边形(德克萨斯州有914231个)

我正在寻找一种更快的方法。我的代码如下

使用的数据集可从美国人口普查中获得:

#/usr/bin/env蟒蛇3
作为gpd导入geopandas
将geopandas_fast_sjoin作为gpfsj导入
导入时间
导入操作系统
进口泡菜
导入系统
os.environ[“GDAL_数据”]=“/usr/share/GDAL”
TRACT_FILE=“./data/tracts/tl_2010{fips}\u tract10.shp”
BLOCK_FILE=“./data/blocks/tabblock2010{fips}\u popu.shp”
投影='+proj=aea+lat_1=29.5+lat_2=45.5+lat_0=37.5+lon_0=-96+x_0=0+y_0=0+ellps=GRS80+datum=NAD83+units=m+no_defs'
打印(“读取数据…”)
开始时间=time.time()
tracts=gpd.read\u文件(TRACT\u file.format(fips=48))
blocks=gpd.read\u文件(BLOCK\u file.format(fips=48))
打印('Time:',Time.Time()-开始时间)
打印(“转换坐标参考系…”)
开始时间=time.time()
线束=线束到crs(投影)
块=块。到crs(投影)
打印('Time:',Time.Time()-开始时间)
打印(“执行空间连接…”)
开始时间=time.time()
joined=gpd.sjoin(域、块、how='left')
打印('Time:',Time.Time()-开始时间)
打印(“计算相交区域…”)
开始时间=time.time()
已连接['area_of_intersect']=[行['geometry'].交叉点(blocks.loc[行['index_right']].['geometry'])。已连接的i行的区域。ItErrorws()]
打印('Time:',Time.Time()-开始时间)

有几种优化可以使这个操作更快:C++中的所有工作都不涉及Python,使用空间索引快速识别交叉口的候选,使用准备好的几何图形快速检查候选,并在可用内核上并行化整个操作。 所有这些都可以在Python中完成,但有一些开销的缺点,除了在我的测试中,在您的千兆字节数据集上使用多处理模块会导致Python耗尽可用内存之外。在Windows上,这可能是不可避免的,而在Linux上,写时拷贝应该可以阻止它。也许可以通过仔细编程来完成,但是使用Python的全部目的是不必担心这些细节。因此,我选择将计算迁移到C++。 为了实现这一点,我构建了一个新的Python模块,该模块从geopandas接受几何体列表,并生成三个列表的输出:(1)左侧几何体的行索引;(2) 右侧几何图形的行索引;(3) 两者之间的重叠区域(仅当>0时)

例如,对于几何图形左=[A,B,C,D]和右=[E,F,G,H]的输入, 让我们:

  • 我们完全陷入困境
  • F与A和B重叠
  • G和H不重叠
然后返回的结果如下所示:

List1 List2 List3
A     E     Area(E)
A     F     AreaIntersection(A,F)
B     F     AreaIntersection(B,F)
在我的机器上,
sjoin
操作耗时73秒,计算交叉点耗时1066秒,总计1139秒(19分钟)

在我的12核机器上,下面的代码需要50秒才能完成所有这一切

因此,对于需要相交区域的空间连接,这只节省了一点时间。但是,对于需要相交区域的空间连接,这可以节省大量时间。换句话说,计算所有这些交叉点需要很多工作

在进一步测试中,在不使用准备好的加速几何图形的情况下,计算交叉区域的时间为287秒,共12个岩芯。因此,平行交叉口的速度可提高4倍,平行于准备好的几何图形的速度可提高23倍

生成文件 快速加入.cpp
#定义地理位置\u仅使用\u R\u API 1
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#ifdef\u OPENMP
#包括
#否则
#定义omp_get_max_线程()1
#定义omp\u get\u thread\u num()0
#恩迪夫
///快速空间连接
///
///@参数gp_左数据框中的GEOS几何体指针的左列表。
///如果gp_left由相对较小的
///较少且相对较大的几何图形。
///@参数gp_右数据框中GEOS几何体指针的右列表
///如果gp_right由相对独立的
///更多和相对较小的几何体。
///
///GEOS几何体指针列表可通过以下方式获取:
///geos_指针=[x.\u几何体用于df['geometry']]
///
///GeoPandas中的一项常见任务是获取两个数据帧并组合它们的数据帧
///基于内容几何体重叠程度的内容。但是,
///GeoPandas中的操作很慢,因为大部分操作都是在Python中执行的。
//这里,我们将整个计算卸载到C++中,并使用了一些技术。
///取得良好的业绩。
///
///也就是说,我们从左侧几何体创建一个空间索引。每人
///从右手边的几何图形,这让我们能够非常快速地找到
///它可能与左侧的几何体重叠。对于上的每个几何体
///在左边,我们创建了一个“准备好的几何体”,这加速了简单的
///通过
///数量级。最后,我们将整个计算并行化
///计算机的线程数。
///
///@返回三个列表:(1)左侧几何图形的行索引;(2) 行索引
///右侧几何图形的定义;(3) 两者之间的重叠区域(仅限
///如果>0)。
///
///例如,对于几何图形左=[A,B,C,D]和右=[E,F,G,H]的输入,
///让我们:
all:
    $(CXX) -O3 -g -shared -std=c++11 -I include `python3-config --cflags --ldflags --libs` quick_join.cpp -o geopandas_fast_sjoin.so -fPIC -Wall -lgeos -fopenmp