python - 如何矢量化比较来自两个不同数据帧的形状对象的函数?
问题描述
我有一个 pandas 数据框和一个 geopandas 数据框。在 Pandas 数据框中,我有一列Points包含shapely.geometry
Point
对象。geopandas 框架中的几何列有Polygon
对象。我想做的是Point
在 Pandas 框架中取一个并测试它是否是geopandas 框架中的within
任何Polygon
对象。
在熊猫框架的新列中,我想要以下内容。如果Point
在给定的范围内Polygon
(即within
调用返回True
),我希望 ' 行中的新列值是 geopandas 框架Point
中 ' 行中不同列的值。Polygon
我对这个问题有一个可行的解决方案,但它不是矢量化的。是否可以对其进行矢量化?
例子:
import geopandas as gpd
import pandas as pd
from shapely.geometry import Point, Polygon
# Create random frame, geometries are supposed to be mutually exclusive
gdf = gpd.GeoDataFrame({'A': [1, 2], 'geometry': [Polygon([(10, 5), (5, 6)]), Polygon([(1,2), (2, 5))]})
# Create random pandas
df = pd.DataFrame({'Foo': ['bar', 'Bar'], 'Points': [Point(4, 5), Point(1, 2)]})
# My non-vectorized solution
df['new'] = ''
for i in df.index:
for j in gdf.index:
if df.at[i, 'Points'].within(gdf.at[j, 'geometry']):
df.at[i, 'new'] = gdf.at[j, 'A']
这很好用,因此当点在多边形内时,df['new']
它将包含列中的任何内容。gdf['A']
我希望有办法让我对这个操作进行矢量化。
解决方案
Points
您可以计算和的所有点之间的欧几里得距离Polygon
。而且,只要距离等于 0,这将为您提供一个交点。我的方法如下。请注意,我把从您的数据帧中获取所有点和多边形点的部分留给您。可能,类似的功能pandas.Series.toList
应该提供。
import numpy as np
from scipy.spatial.distance import cdist
polygon = [[10,5],[5,6],[1,2],[2,5]]
points = [[4,5],[1,2]]
# return distances between all the items of the two arrays
distances = cdist(polygon,points)
print(distances)
[[6. 9.48683298]
[1.41421356 5.65685425]
[4.24264069 0. ]
[2. 3.16227766]]
我们现在要做的就是获取数组中 0 的索引。如您所见,我们的交点在第 3 行和第 2 列,即多边形的第 3 项或点的第 2 项。
for i,dist in enumerate(distances.flatten()):
if dist==0:
intersect_index = np.unravel_index(i,shape=distances.shape)
intersect_point = polygon[intersect_index[0]]
print(intersect_point)
[1,2]
这应该为您提供您正在寻找的矢量化形式。
推荐阅读
- html - 我无法弄清楚为什么工具提示(文本和提示)在固定的页眉和页脚 div 上流血
- javascript - 为什么我需要按两次按钮才能使此功能起作用?
- python - 从所有其他行中减去每一行并在python中查看为矩阵
- tfs - TFS 2012 讨论用户
- flask - Gunicorn:guicorn.log 中显示的响应时间与触发时间 curl 的时间不同
- python - 从紧凑的熊猫数据框中创建图形的最佳方法是什么?
- python - 如何删除熊猫自动生成的行和列
- java - 使用带有 REST 方法的 java 代码发送 XML 请求并从 API 读取 XML 响应(Insomnia / SoapUI)
- android - 改造 @Body 将给定的身体数据转换为数组
- java - 相互 TLS 适用于 Postman 或 SoapUI,但不适用于 Java / Springboot