Created
April 13, 2021 09:34
-
-
Save tastatham/399332a8ff2edff31c3fa94d17eb3883 to your computer and use it in GitHub Desktop.
Updated Geopandas (constant) multi-ring buffer function with example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pandas as pd | |
import geopandas as gpd | |
def multi_ring_buffers(gdf, number, distance): | |
""" | |
Apply a function to a GeoDataFrame containing Point data and compute constant multi-ring buffers | |
Parameters | |
---------- | |
gdf : A GeoDataFrame containing Point data | |
number : Number of ring buffers to compute | |
distance : Constant distance between ring buffers | |
Returns | |
------- | |
A GeoDataFrame containing constant multi-ring buffers for each Point in GeoDataFrame | |
""" | |
# Define default geometry column | |
DEFAULT_GEO_COLUMN_NAME = "geometry" | |
# Define max distance from point toouter ring buffer | |
max_distance = (number * distance) | |
# Calculate the distance intervals between each buffer | |
buffer_ls = list(range(max_distance + distance)[distance::distance] ) | |
# Ignore the first buffer because we don't want to create a ring buffer for this | |
outer_buffer_ls = buffer_ls[1:] | |
# Ignore the last buffer because we can't create a ring buffer for the last outer value | |
inner_buffer_ls = buffer_ls[:-1] | |
# Create first buffer | |
first_buff = gdf.buffer(distance).to_frame(name = DEFAULT_GEO_COLUMN_NAME) | |
# Define inner and outer buffers | |
outer_buffers = [gdf.buffer(buff).to_frame(name = DEFAULT_GEO_COLUMN_NAME) for buff in outer_buffer_ls ] | |
inner_buffers = [gdf.buffer(buff).to_frame(name = DEFAULT_GEO_COLUMN_NAME) for buff in inner_buffer_ls ] | |
# Create empty list | |
sym = [] | |
# Loop through each combination of inner and outer buffers and run a symmetrical difference to create ring buffers | |
[sym.append(gpd.overlay(inner_buffers[buff], outer_buffers[buff], how = "symmetric_difference") ) for buff in range(len(outer_buffers))] | |
# Concat list of ring buffers | |
sym = pd.concat(sym) | |
# Merge first buffer with ring buffers | |
ring_buffers = pd.concat([first_buff, sym]) | |
# Add buffer distance as attribute | |
ring_buffers['buffer'] = buffer_ls | |
return(ring_buffers) | |
# Queen square bristol - Equestrian Statue of William III | |
lng = -2.5947 | |
lat = 51.4505 | |
# Create DataFrame from lat, lon coordinates | |
df = pd.DataFrame({'x':[lng], 'y':[lat] } ) | |
# Create GeoDataFrame from DataFrame and reproject to british national grid | |
gdf = gpd.GeoDataFrame(df, | |
geometry = gpd.points_from_xy(df['x'], df['y']), | |
crs = 4326).to_crs(27700) | |
# Number of ring buffers | |
number = 10 | |
# Distance between ring buffers | |
distance = 10 | |
# Create ring buffers | |
ring_buffers = multi_ring_buffers(gdf, number, distance) | |
# Plot ring buffers | |
ring_buffers.plot(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
could also be done using something like;