如何有效地计算两个geopandas几何之间的距离

13z8s7eq  于 2023-04-28  发布在  其他
关注(0)|答案(1)|浏览(352)

我有两个geopandas数据框,一个是点几何,一个是线几何,我正在计算几何之间的距离。对于每个点,我计算到相关线几何的距离,其线几何id存储在点 Dataframe 的列中以供参考。有321。计算距离的113个点要素。
我正在尝试使用列表理解,但它仍然需要大量的时间。太长了,因为我需要为更大的数据集做更多的点特征。到目前为止,我的代码如下:

def get_distance(point_lineID, point_FID, point_GEOM, lines_df, points_df):

    ref_line = lines_df.loc[lines_df["line_id"] == point_lineID]

    try:
        d = point_GEOM.distance(ref_line["geometry"]).values[0]
        
    except IndexError:
        d = -99
        

    # Add value to frame
    row_num = points_df[points_df["point_id"] == point_FID].index
    points_df.loc[row_num, "distance_mp"] = d

result = [
    get_distance(point_lineid, point_fid, point_geom, df_lines, df_points)
    for point_lineid, point_fid, point_geom in zip(
        points["line_id"], points["point_id"], points["geometry"]
    )
]

我怎样才能让它更有性能?这将是可怕的在这里有一些支持与解释。

nmpmafwu

nmpmafwu1#

有几种方法可以潜在地提高代码的性能。以下是一些建议:
使用矢量化:您可以使用矢量化操作一次性计算所有距离,而不是迭代点DataFrame中的每一行。例如,可以将apply方法与lambda函数一起使用,以便将距离计算一次应用于所有行:

def get_distance(row, lines_df):
    ref_line = lines_df.loc[lines_df["line_id"] == row["line_id"]]
    try:
        return row["geometry"].distance(ref_line["geometry"]).values[0]
    except IndexError:
        return -99

points["distance_mp"] = points.apply(lambda row: get_distance(row, df_lines), axis=1)

使用空间索引:如果lines_df DataFrame非常大,则使用空间索引(如R树)可以显著加快距离计算。你可以使用geopandas。sindex模块为lines_df DataFrame创建空间索引:

from geopandas.sindex import RTree

# Create spatial index
index = RTree(lines_df.geometry)

def get_distance(row, index, lines_df):
    # Find nearest line using spatial index
    nearest_line_idx = list(index.nearest(row["geometry"].bounds))[0]
    nearest_line = lines_df.loc[nearest_line_idx]

    try:
        return row["geometry"].distance(nearest_line["geometry"])
    except IndexError:
        return -99

points["distance_mp"] = points.apply(lambda row: get_distance(row, index, df_lines), axis=1)

使用Cython或Numba:如果距离计算是代码中的瓶颈,可以考虑使用Cython或Numba来加快计算速度。这些工具可以将Python代码分别编译为更快的C代码或机器代码。下面是一个使用Numba的例子:

import numba as nb

@nb.jit(nopython=True)
def get_distance(point_lineID, point_GEOM, lines_df, line_lengths):
    min_dist = np.inf
    for i in range(len(lines_df)):
        if lines_df[i]["line_id"] == point_lineID:
            dist = point_GEOM.distance(lines_df[i]["geometry"])
            if dist < min_dist:
                min_dist = dist
                line_length = line_lengths[i]
    return min_dist, line_length

# Precompute line lengths for faster access
df_lines["length"] = df_lines["geometry"].length

# Create array of line lengths
line_lengths = df_lines["length"].values

distances = np.zeros(len(points))
for i in nb.prange(len(points)):
    distances[i], line_length = get_distance(points["line_id"][i], points["geometry"][i], df_lines, line_lengths)
    if distances[i] == -1:
        distances[i] = -99
points["distance_mp"] = distances

相关问题