How to Calculate Area and Distance in GeoPandas (Correctly)
A common GIS mistake is to calculate polygon area or feature distance directly from data in a geographic CRS such as `EPSG:4326`.
Problem statement
A common GIS mistake is to calculate polygon area or feature distance directly from data in a geographic CRS such as EPSG:4326.
This usually produces wrong results because geographic coordinates are stored in degrees, not meters. GeoPandas will still return numeric values from .area, .length, or .distance(), but those values are based on the coordinate units of the geometry. If your data is in latitude/longitude, the numbers are not reliable for real-world measurement.
In practice, users are usually trying to do one of these tasks:
- calculate polygon area
- calculate line length
- calculate distance between points or other features
The practical fix is to reproject the data to a suitable projected CRS first, then run the measurement.
Quick answer
To calculate area in GeoPandas or measure distance correctly:
- Check the current CRS with
.crs - Reproject to a suitable projected CRS with
.to_crs() - Use:
.areafor polygon area.lengthfor line length.distance()for distances between geometries
import geopandas as gpd
gdf = gpd.read_file("parcels.shp")
# Reproject to a projected CRS with suitable linear units
gdf_proj = gdf.to_crs("EPSG:32633")
# Polygon area in square meters if the CRS uses meters
gdf_proj["area_m2"] = gdf_proj.area
The output units come from the CRS units. In many projected CRSs those units are meters, but some projected CRSs use other units such as feet.
Step-by-step solution
Check the current CRS
Start by checking whether your layer is in a geographic CRS like EPSG:4326.
import geopandas as gpd
gdf = gpd.read_file("parcels.shp")
print(gdf.crs)
If you see something like EPSG:4326, your coordinates are in degrees. That is fine for storage and web mapping, but not for accurate area and distance measurements.
Choose a suitable projected CRS
You need a projected CRS that fits your study area and task.
Common practical choices:
- Local UTM zone for city or regional data
- National projected CRS for country-specific workflows
- Equal-area CRS when area accuracy is the main priority
Examples:
EPSG:32633— UTM zone 33N (only appropriate for data in that zone)EPSG:27700— British National GridEPSG:5070— NAD83 / Conus Albers for US-wide area analysis
For small to medium study areas, a local UTM CRS is often a good default. For large regions, CRS choice matters more because one projected CRS may not preserve both area and distance equally well everywhere.
Reproject the GeoDataFrame
Use .to_crs() to create a projected copy.
gdf_proj = gdf.to_crs("EPSG:32633")
This keeps the original gdf unchanged and gives you a new GeoDataFrame for measurement.
Calculate polygon area
After reprojection, use .area.
gdf_proj["area_m2"] = gdf_proj.area
If the CRS uses meters, the result is square meters.
You can also convert to hectares or square kilometers:
gdf_proj["area_ha"] = gdf_proj["area_m2"] / 10_000
gdf_proj["area_km2"] = gdf_proj["area_m2"] / 1_000_000
Calculate line length
For roads, rivers, or utility lines, use .length after reprojection.
lines = gpd.read_file("roads.shp")
lines_proj = lines.to_crs("EPSG:32633")
lines_proj["length_m"] = lines_proj.length
lines_proj["length_km"] = lines_proj["length_m"] / 1000
Calculate distance between two geometries
Use .distance() when comparing geometries in the same projected CRS.
points = gpd.read_file("sites.shp").to_crs("EPSG:32633")
distance_m = points.geometry.iloc[0].distance(points.geometry.iloc[1])
print(distance_m)
For two layers, both must use the same CRS:
schools = gpd.read_file("schools.shp").to_crs("EPSG:32633")
hospitals = gpd.read_file("hospitals.shp").to_crs("EPSG:32633")
schools["dist_to_first_hospital_m"] = schools.geometry.distance(
hospitals.geometry.iloc[0]
)
Code examples
Example 1: Calculate polygon area in square meters
import geopandas as gpd
parcels = gpd.read_file("data/parcels.shp")
print("Original CRS:", parcels.crs)
# Reproject to a projected CRS with meter units
parcels_proj = parcels.to_crs("EPSG:32633")
# Calculate area
parcels_proj["area_m2"] = parcels_proj.area
print(parcels_proj[["area_m2"]].head())
# Optional: save result
parcels_proj.to_file("output/parcels_with_area.shp")
Example 2: Convert area to hectares and square kilometers
parcels_proj["area_ha"] = parcels_proj["area_m2"] / 10_000
parcels_proj["area_km2"] = parcels_proj["area_m2"] / 1_000_000
print(parcels_proj[["area_m2", "area_ha", "area_km2"]].head())
Example 3: Calculate line length in meters
import geopandas as gpd
roads = gpd.read_file("data/roads.shp")
roads_proj = roads.to_crs("EPSG:32633")
roads_proj["length_m"] = roads_proj.length
print(roads_proj[["length_m"]].head())
Example 4: Calculate distance between points
import geopandas as gpd
origins = gpd.read_file("data/origins.shp").to_crs("EPSG:32633")
destinations = gpd.read_file("data/destinations.shp").to_crs("EPSG:32633")
origins["distance_to_first_dest_m"] = origins.geometry.distance(
destinations.geometry.iloc[0]
)
print(origins[["distance_to_first_dest_m"]].head())
Example 5: Calculate nearest-feature distance
A practical pattern is to find the nearest feature in another layer, then measure the distance.
import geopandas as gpd
buildings = gpd.read_file("data/buildings.shp").to_crs("EPSG:32633")
bus_stops = gpd.read_file("data/bus_stops.shp").to_crs("EPSG:32633")
nearest = gpd.sjoin_nearest(
buildings,
bus_stops,
how="left",
distance_col="nearest_dist_m"
)
print(nearest[["nearest_dist_m"]].head())
Note: gpd.sjoin_nearest() requires a recent GeoPandas version and a working spatial index backend in your environment.
Explanation
The key issue is the difference between a geographic CRS and a projected CRS.
A geographic CRS stores coordinates on the earth using angular units such as latitude and longitude. EPSG:4326 is the most common example. In this CRS, coordinates are in degrees, so geometry calculations based on raw coordinate values do not represent meters or square meters.
A projected CRS transforms the curved earth surface into a flat coordinate system. Its units are often meters or feet. That makes it suitable for planar measurements such as area, line length, and distance between features.
GeoPandas does not automatically decide whether your CRS is appropriate for measurement. It simply uses the geometry coordinates as they are:
.areareturns area in CRS units squared.lengthreturns length in CRS units.distance()returns distance in CRS units
So if your data is in degrees, your output is also degree-based, which is usually not what you want.
For accurate GeoPandas area calculation and distance measurement, reproject first, then measure.
Edge cases and notes
Data in EPSG:4326 gives misleading results
You can run .area or .distance() on data in EPSG:4326, but the results are not suitable for real-world measurement. The values may look valid because they are numeric, but they are based on degrees.
Missing CRS metadata
If gdf.crs is None, do not use .to_crs() yet. First assign the correct existing CRS with .set_crs(), then reproject if needed.
gdf = gdf.set_crs("EPSG:4326")
gdf_proj = gdf.to_crs("EPSG:32633")
Both layers must use the same CRS for distance calculations
If you calculate distance between two layers, align both to the same projected CRS first.
layer1 = layer1.to_crs("EPSG:32633")
layer2 = layer2.to_crs("EPSG:32633")
Multipolygon and multiline geometries
Multipart geometries still work with .area and .length. The result is the total area or total length of the full geometry.
Large study areas need careful CRS selection
A single local projected CRS may work well for one city or region but perform poorly across a continent. If you are measuring over large areas, choose a CRS designed for that extent and purpose. For some large-extent workflows, a geodesic approach may be more appropriate than using one projected CRS for everything.
Geometry validity can affect results
Invalid polygons can produce unreliable area values. If results look wrong, check geometry validity.
invalid = ~gdf.geometry.is_valid
print(gdf[invalid])
If needed, repair invalid geometries before measurement.
Internal links
For the CRS background behind this workflow, see Geographic vs Projected CRS in GeoPandas.
If you need the reprojection step itself, read How to Reproject Spatial Data in Python (GeoPandas).
For line-specific measurement workflows, see How to Calculate Line Length in GeoPandas.
If your numbers still look incorrect, check Why GeoPandas Area or Distance Values Are Wrong.
FAQ
How do I calculate area in GeoPandas in square meters?
Reproject your polygon layer to a projected CRS that uses meters, then use .area.
gdf_proj = gdf.to_crs("EPSG:32633")
gdf_proj["area_m2"] = gdf_proj.area
Why is GeoPandas giving incorrect area or distance values?
The most common reason is that your data is in a geographic CRS such as EPSG:4326. In that case, coordinates are in degrees, so area and distance calculations are not in meters.
What CRS should I use to calculate distance in GeoPandas?
Use a projected CRS appropriate for your study area. For regional work, a local UTM zone is often a practical choice. For country-scale or area-focused analysis, a national or equal-area CRS may be better.
Do both GeoDataFrames need the same CRS for .distance()?
Yes. Both layers should be in the same projected CRS before running .distance() or nearest-distance workflows.
Can I calculate area directly in EPSG:4326?
You can, but the result will not be a reliable real-world area measurement. For correct values, reproject first.
Related articles
Keep exploring with more guides in this category.
How to Fix Invalid Geometries in Python (GeoPandas)
How to find and fix invalid geometries in GeoPandas using buffer(0), make_valid, and geometry validation checks.
Read article →
How to Read a Shapefile in Python with GeoPandas
Step-by-step guide to reading a shapefile in Python using GeoPandas, with examples and common issues covered.
Read article →
How to Reproject Spatial Data in Python (GeoPandas)
How to reproject spatial data in Python using GeoPandas to_crs(), with examples for common coordinate systems.
Read article →