# Creating buffers in meters for locations around the world using Python

I have a location dataset (points long & lat) for events that happened around the World. I want to create 5km rings around these locations using `Geopandas.buffer` function. Following in a previous post How to use GeoPandas buffer function to get buffer zones in kilometers?, I first transform to meters and then compute the buffers.

I realize that EPSG:32634 is not appropriate for every country and appears to lead to distortions in the size of these buffers. Do I have to manually pick the "best" projection for each point or is there a way to code this? Or is the transformation to meters actually not needed?

I need to compute some statistics for the area within each of these buffers. I have to make sure that the size of the buffers is the same around the world. I don't need them for visualization purposes.

You can use `.estimate_utm_crs` method to find a suitable utm crs for each point, reproject to this and buffer:

``````import geopandas as gpd
import shapely

buffer_distance = 1000000 #Buffer radius in meters

#Create a point dataframe with 10 points around the world in EPSG:4326 coordinates
wkt_list = ['Point (146.66667606373533772 62.23890379786246285)',
'Point (34.32764669470472541 -41.38552524503352714)',
'Point (49.8860350310458216 -4.91479315765549529)',
'Point (-83.06099993189856434 14.366032762331713)',
'Point (-70.56585431584979062 -16.25292544986456278)',
'Point (-101.91449225955174995 -48.47418794019157673)',
'Point (-122.57824978678837624 -42.82228245839684888)',
'Point (-166.26390599168405515 -32.96525451181832267)',
'Point (-100.36153965087687823 26.92149042530141401)',
'Point (-125.12779657560248836 50.35334977372303911)']
geometries = [shapely.wkt.loads(x) for x in wkt_list]
df = gpd.GeoDataFrame(geometry=geometries, crs=4326)

df["id"] = range(0, df.shape[0]) #Create a unique id for each point/row

buffer_geometries = [] #A list to hold buffered points
for idnum, subframe in df.groupby("id"): #For each row
estimated_utm = subframe.estimate_utm_crs() #Estimate a utm crs
subframe = subframe.to_crs(estimated_utm) #Reproject the point to this
subframe = subframe.buffer(distance=buffer_distance) #Buffer the point
buffer_geometries.append(subframe.to_crs(4326)) #Reproject the resulting series back to 4326 and append to list

new_geoms = gpd.pd.concat(buffer_geometries) #From a list of series to a data frame

result = df.copy()
result["geometry"] = new_geoms

#Plot
world_map = gpd.read_file("https://datahub.io/core/geo-countries/r/countries.geojson") #A world map for plotting (23 MB)
ax = world_map.plot(figsize=(20,10), facecolor="honeydew", edgecolor="black")
result.plot(ax=ax, facecolor="#FFC107", edgecolor="#004D40")
df.plot(ax=ax, color="#D81B60", markersize=80)
``````

EPSG 3857 is a geodetic CRS that is measured in meters. I'd recommend transforming to that projection then perform your buffer and analysis.