Site icon Peter Horton

Geopandas Shapefile Adjacency

The below code takes in a geodataframe and a unique column and returns a dictionary mapping from each unique column value to a list of the column values it is adjacent too.

As written, the code uses a buffer of 1 in the 3857 crs and, as you can see below, accounts for point (Queen’s) adjacency.

The next version of the code will attempt to do the same thing without using a buffer and return an adjacency matrix rather than a dictionary.

def calculate_adjacency(gdf, unique_col):
    '''
    Code that takes a geodataframe and returns a dictionary of adjacencies
    '''
    
    # Convert to a crs to make sure the buffer area works
    gdf = gdf.to_crs(3857)
    
    # Make a copy of the GeoDataFrame
    gdf_buffer = gdf.copy(deep = True)
    
    # Add a buffer of 1 to the geometry of the copied GeoDataFrame
    gdf_buffer["geometry"] = gdf.buffer(1)
    
    # Intersected the GeoDataFrame with the buffer with the original GeoDataFrame
    test_intersection = gp.overlay(gdf_buffer, gdf, how = "intersection")
    
    # Define a tuple of zips of the unique_col pairs present in the intersection
    test_intersection_tuples = tuple(zip(test_intersection[unique_col+"_1"], test_intersection[unique_col+"_2"]))
    
    # Define a dictionary that will map from a unique_col value to a list of other unique_cols it is adjacent to
    final_dict = {}
    
    # Iterate over the tuples
    for val in test_intersection_tuples:
        
        # The shapes will intersect with themselves, we don't want to add these to the dictionary
        if val[0] != val[1]:
            
            # If the shape is already in the dictionary
            if val[0] in list(final_dict.keys()):
                
                # Append the adjacent shape to the list
                holder = final_dict[val[0]]
                holder.append(val[1])
                final_dict[val[0]] = holder
            else:
                
                # Otherwise, create a key in the dictionary mapping to a list with the adjacenct shape
                final_dict[val[0]] = [val[1]]
                
    # Some shapes will only intersect with themselves and not be added to the above
    for val in [i for i in gdf[unique_col] if i not in list(final_dict.keys())]:
        
        # For each of these, add a blank list to the dictionary
        final_dict[val] = []
        
    # Return the adjacency dictionary    
    return final_dict

Example output from running the code on a shape file of the US States from the census.

Exit mobile version