Measuring Areas and Distances#

Understanding how to measure areas and distances is a key part of working with spatial data — and it’s no coincidence that this section comes right after the blocks on coordinate systems.

That’s because accurate calculations of distance, area, and even buffer zones all depend heavily on the coordinate reference system (CRS) you’re using.

If your data is in a geographic CRS (like WGS 84), coordinates are expressed in degrees, which are not suitable for direct distance or area calculations.
To get correct results in meters or square meters, your data needs to be projected into an appropriate projected CRS, like UTM.

In this section, we’ll explore how to measure distances and areas correctly — and why choosing the right projection is essential.

Import libraries#

import geopandas as gpd
import pandas as pd
import osmnx as ox

Export City Boundary#

admin_border = ox.geocode_to_gdf('Vienna, Austria')
admin_border.explore(tiles='cartodbpositron')
Make this Notebook Trusted to load map: File -> Trust Notebook

In GeoPandas, every GeoDataFrame has a special attribute called .geometry, which stores the geometric shapes of the spatial features — for example, points, lines, or polygons.
This attribute gives you direct access to the geometry of each object in your dataset.

Once you have access to the geometry, you can perform various spatial operations.
One particularly useful method is .area, which calculates the area of each polygon feature.

But here’s an important note: the .area method returns correct values only if your data is in a projected CRS (like UTM), where coordinates are in meters.
If your data is still in degrees (e.g., EPSG:4326), the area values will be meaningless.

Now that we’ve reprojected our dataset into a suitable UTM zone, we can safely use the .area method to calculate the area of each polygon.

Let’s create a new column called "area" in our admin_okrug GeoDataFrame and store the calculated area values there:

admin_okrug["area"] = admin_okrug.geometry.area
admin_border['area'] = admin_border.geometry.area

admin_border.head()
/var/folders/ry/9bb7wrz54vq_kn2ytlj6ynzm0000gn/T/ipykernel_49378/1924210537.py:1: UserWarning: Geometry is in a geographic CRS. Results from 'area' are likely incorrect. Use 'GeoSeries.to_crs()' to re-project geometries to a projected CRS before this operation.

  admin_border['area'] = admin_border.geometry.area
geometry bbox_west bbox_south bbox_east bbox_north place_id osm_type osm_id lat lon class type place_rank importance addresstype name display_name area
0 POLYGON ((16.18183 48.17112, 16.1819 48.17103,... 16.181831 48.117907 16.577513 48.322668 408340724 relation 109166 48.208354 16.372504 boundary administrative 7 0.818783 city Vienna Vienna, Austria 0.050199

And here’s the problem — the area values look strange and way too small. What’s going on?

Let’s think back to the coordinate system of this layer… it’s geographic, which means the units are in degrees, not meters.
As a result, all area calculations are also in degrees² — which isn’t meaningful for real-world measurements.

🛑 Always pay attention to the “UserWarning” you might see when calculating areas (like we did above). It often points out that the results are likely incorrect because the data is still in a geographic CRS. It also reminds you that you need to reproject your data to a suitable projected CRS to get accurate results.

admin_border_utm = admin_border.to_crs(admin_border.estimate_utm_crs())

admin_border_utm['area_utm'] = admin_border_utm.geometry.area

admin_border_utm.head()
geometry bbox_west bbox_south bbox_east bbox_north place_id osm_type osm_id lat lon class type place_rank importance addresstype name display_name area area_utm
0 POLYGON ((587866.661 5335995.06, 587872.091 53... 16.181831 48.117907 16.577513 48.322668 408340724 relation 109166 48.208354 16.372504 boundary administrative 7 0.818783 city Vienna Vienna, Austria 0.050199 4.146378e+08

Now that looks more realistic — and yes, the values are in square meters!

This kind of notation might not be familiar to everyone, so let’s break it down with an example:
4.146378e+08 means 4.146378 × 108, i.e., 414,637,800 square meters, which is 414.6378 square kilometers (≈ 414.6 km²).

Summary#

In this section, we covered how to measure areas and distances correctly in GeoPandas.

We learned to:

  • Recognize that geographic CRS (e.g., EPSG:4326) stores coordinates in degrees, which aren’t suitable for measurements.

  • Reproject data to an appropriate projected CRS (e.g., UTM) using to get results in meters and square meters.

With the right CRS, distance, area, and buffer calculations become accurate and reliable.