How to find index of nearest geometry using Geopandas

Viewed 90

this is an extension of the question at How to find index of nearest geometry. I need to find the closest point in the Geopandas DF target_df to each point in the Geopandas DF source_df. I can do this using shapely but when I try to apply the shapely code using Geopandas I get this error 'TypeError: unhashable type: 'GeoDataFrame'. The code is below:

import geopandas as gpd
import shapely

# Return the field COLUMN of the nearest point in TARGET_DF to each point in SOURCE_DF

def nearest(source_df, target_df, trg_column=None):

    # Merge target DF points into MultiPoint object
    
    mpts = target_df.geometry.unary_union         
    
    # Find the closest point
    
    curr_pt, near_pt = shapely.ops.nearest_points(source_df['geometry'], mpts)
    nearest = target_df['geometry'] == near_pt
    
    # Get the corresponding value from TARGET_DF
    
    value = target_df[nearest][trg_column].values[0]
    
    return value

# MAIN program

if __name__ =="__main__":
    
    # Define dataframe of target points
    
    df_targ = gpd.GeoDataFrame([['point A', shapely.geometry.Point(1,1)], 
                                ['point B', shapely.geometry.Point(2,2)],
                                ['point C', shapely.geometry.Point(3,3)],
                                ['point D' ,shapely.geometry.Point(4,4)]], 
                                 columns=['t_name', 'geometry'])
    
    # Define points to process and store in GeoPandas DF
    
    dx = 0.1
    dy = 0.1
    
    pt_list = []
    for indx, pt in enumerate(df_targ['geometry']):
        new_pt = shapely.geometry.Point(pt.x + dx, pt.y + dy)
        nname = "target_%1d" % indx 
        pt_list.append([nname, new_pt])
    
    df_sorc = gpd.GeoDataFrame(pt_list, columns=['s_name', 'geometry'])
    
    # Find nearest point using shapely
    
    mpts = df_targ.geometry.unary_union         # Merge DF points into MultiPoint object
    
    print("Using shapely:")
    for pt in df_sorc['geometry']:
        curr_pt, near_pt = shapely.ops.nearest_points(pt, mpts)
    
        near_nam = df_targ.loc[df_targ['geometry'] == near_pt, 't_name'].values[0]
        print("nearest point to (%3.1f, %3.1f) is %s" % (pt.x, pt.y, near_nam))
    
    # Find nearest point using Geopandas
    
    df_sorc['nearest_pt'] = df_sorc.apply(nearest, df_targ, trg_column='t_name')
    print(df_sorc.head())

I tried changing the apply statement as follows:

    df_sorc['nearest_pt'] = df_sorc.apply(nearest, df_targ, trg_column='t_name', axis=1)

but now get this error: TypeError: apply() got multiple values for argument 'axis'. Would appreciate any suggestions. Thanks in advance

1 Answers

I found the answer here: set_axis() got multiple values for argument 'axis'. The issue seems to be that Pandas changed the argument order of the apply function in version 0.21.0. I changed the apply statement to

df_sorc['nearest_pt'] = df_sorc.apply(nearest, axis=1, trg_df=df_targ, trg_col='t_name')

and the apply function def to

def nearest(source_df, trg_df=None, trg_col=None):

to avoid problems with positional arguments. This gives the expected behaviour

Related