Python 对两个shapely对象的numpy数组应用成对shapely函数
我有两个不同长度的数组。一个包含形状优美的多边形,另一个包含形状优美的点。我想为两个数组中元素的每个可能组合运行a_polygon.contains(a_point)shapely函数 我考虑的是,构建一个包含所有行中可能的组合的两列矩阵可能是一个理想的中间步骤。但是当输入数据很大时,“cartersian(arrays)”函数中的循环可能会影响性能 我尝试广播其中一个数组,然后应用shapely函数:Python 对两个shapely对象的numpy数组应用成对shapely函数,python,arrays,numpy,shapely,Python,Arrays,Numpy,Shapely,我有两个不同长度的数组。一个包含形状优美的多边形,另一个包含形状优美的点。我想为两个数组中元素的每个可能组合运行a_polygon.contains(a_point)shapely函数 我考虑的是,构建一个包含所有行中可能的组合的两列矩阵可能是一个理想的中间步骤。但是当输入数据很大时,“cartersian(arrays)”函数中的循环可能会影响性能 我尝试广播其中一个数组,然后应用shapely函数: Polygons_array[:,newaxis].contains(Points_arra
Polygons_array[:,newaxis].contains(Points_array)
但这当然是行不通的。我知道最近发布的geopandas库,但它不是我的雨篷安装的选项 下面的代码显示了如何对包含在两个不同长度数组中的几何对象应用函数。这种方法避免使用循环。熊猫的apply和Numpy。需要矢量化和广播选项
首先考虑做一些导入和以下两个数组:
import numpy as np
import pandas as pd
from shapely.geometry import Polygon, Point
polygons = [[(1,1),(4,3),(4,1),(1,1)],[(2,4),(2,6),(4,6),(4,4),(2,4)],[(8,1),(5,1),(5,4),(8,1)]]
points = [(3,5),(7,3),(7,6),(3,2)]
可以通过以下步骤获得包含多边形和点的几何对象的阵列:
geo_polygons = pd.DataFrame({'single_column':polygons}).single_column.apply(lambda x: Polygon(x)).values
geo_points = pd.DataFrame({'single_column':points}).single_column.apply(lambda x: Point(x[0], x[1])).values
# As you might noticed, the arrays have different length.
现在定义并矢量化了应用于两个数组的函数:
def contains(a_polygon, a_point):
return a_polygon.contains(a_point)
contains_vectorized = np.vectorize(contains)
这样,函数就可以应用于向量中的每个元素。广播点阵列可处理成对求值:
contains_vectorized(geo_polygons, geo_points[:,np.newaxis])
返回以下数组:
array([[False, True, False],
[False, False, False],
[False, False, False],
[ True, False, False]], dtype=bool)
列对应于多边形,行对应于点。该数组中的布尔值显示,例如,第一个点位于第二个多边形内。没关系。映射多边形和点将证明正确:
from descartes import PolygonPatch
import matplotlib.pyplot as plt
fig = plt.figure(1, figsize = [10,10], dpi = 300)
ax = fig.add_subplot(111)
offset_x = lambda xy: (xy[0] + 0.1, xy[1])
offset_y = lambda xy: (xy[0], xy[1] - 0.5)
for i,j in enumerate(geo_polygons):
ax.add_patch(PolygonPatch(j, alpha=0.5))
plt.annotate('polygon {}'.format(i + 1), xy= offset_y(tuple(j.centroid.coords[0])))
for i,j in enumerate(geo_points):
ax.add_patch(PolygonPatch(j.buffer(0.07),fc='orange',ec='black'))
plt.annotate('point {}'.format(i + 1), xy= offset_x(tuple(j.coords[0])))
ax.set_xlim(0, 9)
ax.set_ylim(0, 7)
ax.set_aspect(1)
plt.show()
据我所知,只有当Numpy数组包含基本类型(例如
bool
或double
)时,使用Numpy数组才比较快,而不是像Shapely包中的一般Python对象。很高兴知道这一点。请其他人详细说明一下好吗?顺便说一句,我在下面发布了一种完成整个过程的方法。我想补充一点,在大型数据集的情况下,使用空间索引可能更可取。这样可以避免在相距较远的几何图形之间进行完全相交测试,从而节省计算。例如,请参见。