1

I have two dataframes, one with line features and another one with point features. Each point has the id of an object in the linefeatures-dataset as a value in a column.

Now I need to calculate the minimal distance between each point and its relevant line. For this I have to get the line-id from the point feature and then search it in the line-dataframe, and only then calculate the distance between the two geometries by using GeoPandas method 'distance' like:

def min_distance(point, lines):
    return lines.distance(point).min()

df_points['min_dist_to_lines'] = df_points.geometry.apply(min_distance, args=(df_lines,))

However, before that, I need to check for the line ids. Is there a way to do this efficiently, without iterating both dfs? I have a modest size of data and can imagine, that the iterating will slow down the processing.

3
  • This seems like a pure Python issue, which could be addressed with a dictionary.
    – Vince
    Commented Oct 25, 2023 at 12:42
  • I was not sure, as still need to get access to the geometry objects and the geopandas method 'distance' won't work if the geometry object may only be stored as WKT, or?
    – i.i.k.
    Commented Oct 25, 2023 at 12:45
  • sorry, need to correct my previous commend: when the geom object is only stored as a WKT as string, then I cannot apply the distance function anymore, as it is now not a geometry object anymore but just a string? therefore I cannot store the data as dict or in a list. But maybe I misunderstand here something?
    – i.i.k.
    Commented Oct 25, 2023 at 13:02

1 Answer 1

1

Use merge to join the two dataframes on the shared attribute, then calculate distance:

import geopandas as gpd
line = gpd.read_file(r"C:\GIS\GIStest\lines_with_id.geojson")
point = gpd.read_file(r"C:\GIS\GIStest\points_with_id.geojson")

#The line and point df's both have the column line_id, which should be used to match the point to a line:
#line.columns
#Index(['line_id', 'geometry'], dtype='object')
#point.columns
#Index(['line_id', 'geometry'], dtype='object')

joined = gpd.pd.merge(left=point, right=line, left_on="line_id", right_on="line_id", how="inner") #Create a new dataframe of the matching point and lines in one table
#joined.columns
#Index(['line_id', 'geometry_x', 'geometry_y'], dtype='object') #geometry_x is the point geometry, geometry_y the line geometry

joined["distance"] = joined.apply(lambda x: x["geometry_x"].distance(x["geometry_y"]), axis=1)

Then you can merge the distance back to the line and point df.

2
  • This did work, however, it runs very, very slow. For data sizes > 0.5 GB I would not suggest to use it, even for data about 250MB it runs a couple of minutes.
    – i.i.k.
    Commented Nov 2, 2023 at 14:08
  • It shouldnt be slow. Whats the line.shape and joined.shape?
    – Bera
    Commented Nov 2, 2023 at 17:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.