计算 Shapely 几何对象的成对距离
Calculating pairwise distances for Shapely geometry objects
我是在常规的 Whosebug 而不是 stackexchange GIS 上问这个问题,因为我的问题更多是关于 scikit-learn,而不是任何与 GIS 相关的库。
我有一个包含多边形的 GeoDataFrame(一个 Pandas GeoDataFrame,但具有附加的几何功能),我想计算它们之间的成对距离。我也在使用 scikit-learn,似乎他们为此有一些很好的优化函数,而且你似乎也可以指定一个可调用函数来进行实际距离计算,这很好,因为那样我就可以(我认为)输出距离矩阵时,直接使用Shapely的.distance()
方法获取多边形之间的距离即可。此方法计算两个几何之间的几何距离。
但是,我不知道如何实现自定义可调用函数。这是我目前所拥有的:
import geopandas as gpd
from random import uniform
from shapely.geometry import Point
from sklearn.metrics import pairwise_distances
# Define polygon to polygon distance callable
def poly_distance(poly1, poly2):
return poly1.distance(poly2)
# Make some points and buffer them into polygons
geoms = [Point(uniform(0, 100), uniform(0, 100)) for i in range(100)]
gdf = gpd.GeoDataFrame(geoms, columns=["geometry"], geometry="geometry")
gdf[gdf.geometry.name] = gdf.buffer(1)
X = gdf[gdf.geometry.name].to_numpy()
result = pairwise_distances(X, poly_distance)
我认为这可行,因为我正在指定一个函数,该函数将从结果 numpy 数组 (X
) 中获取两个元素,并且 return 它们之间的浮点距离。但它抱怨:
TypeError: float() argument must be a string or a number, not 'Polygon'
docs 确实说:
The callable should take two arrays from X as input and return a value indicating the distance between them.
但我不知道如何将其转换为函数所需的格式。我还尝试了 X
的以下定义:
X = np.array([gdf[gdf.geometry.name].to_numpy()])
X = np.transpose(np.array([gdf[gdf.geometry.name].to_numpy()]))
但是它们都不起作用。
sklearn 指标期望参数 x
具有可转换为浮点数的有效数据类型。如果您看到源代码,它会在计算它们之间的距离之前将数组转换为浮点数。
由于您的 X 由多边形对象组成,因此在将数组转换为浮点数时出现错误。
但是,您可以构建自己的 pair_wise
函数,它将 polygon array
和 distance function
作为输入并给出 distance matrix
作为输出。
代码:
import geopandas as gpd
from random import uniform
from shapely.geometry import Point
import numpy as np
# Define polygon to polygon distance callable
def poly_distance(poly1, poly2):
return poly1.distance(poly2)
# Make some points and buffer them into polygons
geoms = [Point(uniform(0, 100), uniform(0, 100)) for i in range(100)]
gdf = gpd.GeoDataFrame(geoms, columns=["geometry"], geometry="geometry")
gdf[gdf.geometry.name] = gdf.buffer(1)
X = gdf[gdf.geometry.name].to_numpy()
def pair_wise(x, function):
distance_matrix = []
for element in x:
distance_matrix.append([function(element, item) for item in x])
return np.array(distance_matrix)
pair_wise(X, poly_distance)
我是在常规的 Whosebug 而不是 stackexchange GIS 上问这个问题,因为我的问题更多是关于 scikit-learn,而不是任何与 GIS 相关的库。
我有一个包含多边形的 GeoDataFrame(一个 Pandas GeoDataFrame,但具有附加的几何功能),我想计算它们之间的成对距离。我也在使用 scikit-learn,似乎他们为此有一些很好的优化函数,而且你似乎也可以指定一个可调用函数来进行实际距离计算,这很好,因为那样我就可以(我认为)输出距离矩阵时,直接使用Shapely的.distance()
方法获取多边形之间的距离即可。此方法计算两个几何之间的几何距离。
但是,我不知道如何实现自定义可调用函数。这是我目前所拥有的:
import geopandas as gpd
from random import uniform
from shapely.geometry import Point
from sklearn.metrics import pairwise_distances
# Define polygon to polygon distance callable
def poly_distance(poly1, poly2):
return poly1.distance(poly2)
# Make some points and buffer them into polygons
geoms = [Point(uniform(0, 100), uniform(0, 100)) for i in range(100)]
gdf = gpd.GeoDataFrame(geoms, columns=["geometry"], geometry="geometry")
gdf[gdf.geometry.name] = gdf.buffer(1)
X = gdf[gdf.geometry.name].to_numpy()
result = pairwise_distances(X, poly_distance)
我认为这可行,因为我正在指定一个函数,该函数将从结果 numpy 数组 (X
) 中获取两个元素,并且 return 它们之间的浮点距离。但它抱怨:
TypeError: float() argument must be a string or a number, not 'Polygon'
docs 确实说:
The callable should take two arrays from X as input and return a value indicating the distance between them.
但我不知道如何将其转换为函数所需的格式。我还尝试了 X
的以下定义:
X = np.array([gdf[gdf.geometry.name].to_numpy()])
X = np.transpose(np.array([gdf[gdf.geometry.name].to_numpy()]))
但是它们都不起作用。
sklearn 指标期望参数 x
具有可转换为浮点数的有效数据类型。如果您看到源代码,它会在计算它们之间的距离之前将数组转换为浮点数。
由于您的 X 由多边形对象组成,因此在将数组转换为浮点数时出现错误。
但是,您可以构建自己的 pair_wise
函数,它将 polygon array
和 distance function
作为输入并给出 distance matrix
作为输出。
代码:
import geopandas as gpd
from random import uniform
from shapely.geometry import Point
import numpy as np
# Define polygon to polygon distance callable
def poly_distance(poly1, poly2):
return poly1.distance(poly2)
# Make some points and buffer them into polygons
geoms = [Point(uniform(0, 100), uniform(0, 100)) for i in range(100)]
gdf = gpd.GeoDataFrame(geoms, columns=["geometry"], geometry="geometry")
gdf[gdf.geometry.name] = gdf.buffer(1)
X = gdf[gdf.geometry.name].to_numpy()
def pair_wise(x, function):
distance_matrix = []
for element in x:
distance_matrix.append([function(element, item) for item in x])
return np.array(distance_matrix)
pair_wise(X, poly_distance)