CoursesGIS Basics — A Complete Introduction9.6 Lab — Site Suitability Analysis
Module 9: Vector Spatial AnalysisHands-on Lab

9.6 Lab — Site Suitability Analysis

A classic GIS workflow — use buffers, overlays, and filters to find candidate sites matching multiple criteria.

Lesson 49 of 100·55 min read

Key takeaways

  • Site suitability is the canonical application of the vector analysis tools you've learned.
  • Each criterion becomes a layer; combining layers via intersect / difference yields candidates.
  • The same pattern works for retail, infrastructure, conservation, and public services.

Introduction

You've been hired by a city to find candidate parcels for a new community clinic. Criteria:

  1. Parcel area ≥ 1 500 m².
  2. Zoned residential or mixed-use.
  3. Within 500 m of a major road for accessibility.
  4. Farther than 1 km from an existing clinic.
  5. Not inside any protected area.

By the end of this lab you'll have a ranked list of candidate parcels and a polished map.

Prerequisites

  • PostGIS from Module 8 (or QGIS / GeoPandas alternatives).
  • Sample data: parcels, zoning, roads, existing clinics, protected areas. Use any city's open data or the fictional files in the lab bundle.
  • About an hour.

Step 1 — Load data

Shell
1ogr2ogr -f PostgreSQL PG:"..." parcels.gpkg -nln parcels
2ogr2ogr -f PostgreSQL PG:"..." zoning.gpkg -nln zoning
3ogr2ogr -f PostgreSQL PG:"..." roads.gpkg -nln roads
4ogr2ogr -f PostgreSQL PG:"..." clinics.gpkg -nln clinics
5ogr2ogr -f PostgreSQL PG:"..." protected.gpkg -nln protected

Verify with:

SQL
1SELECT COUNT(*) FROM parcels;
2SELECT COUNT(*) FROM zoning;

Step 2 — Filter by area and zoning

SQL
1CREATE TABLE candidate_1 AS
2SELECT p.*
3FROM parcels p
4JOIN zoning z ON ST_Within(p.geom, z.geom)
5WHERE ST_Area(p.geom) >= 1500
6  AND z.zone_type IN ('residential', 'mixed_use');

How many remain?

SQL
SELECT COUNT(*) FROM candidate_1;

Step 3 — Keep only those near major roads

SQL
1CREATE TABLE road_buffer AS
2SELECT ST_Union(ST_Buffer(geom::geography, 500)::geometry) AS geom
3FROM roads
4WHERE road_class IN ('motorway', 'primary', 'secondary');
5[object Object]
6

Step 4 — Exclude areas near existing clinics

SQL
1CREATE TABLE clinic_buffer AS
2SELECT ST_Union(ST_Buffer(geom::geography, 1000)::geometry) AS geom
3FROM clinics;
4[object Object]
5

Step 5 — Exclude protected areas

SQL
1CREATE TABLE protected_union AS
2SELECT ST_Union(geom) AS geom FROM protected;
3[object Object]
4

Step 6 — Rank candidates

Assume bigger is better, closer to the city centre is better, farther from existing clinics is better.

SQL
1SELECT id,
2       ST_Area(geom) AS area_m2,
3       ST_Distance(geom::geography,
4                   ST_GeogFromText('POINT(12.568 55.676)')) AS dist_centre,
5       (SELECT MIN(ST_Distance(geom::geography, c.geom::geography))
6        FROM clinics c) AS dist_nearest_clinic
7FROM candidate_final
8ORDER BY
9  ST_Area(geom) DESC,
10  dist_centre ASC,
11  dist_nearest_clinic DESC
12LIMIT 10;

Or weight the three criteria into a composite score.

Step 7 — Visualise in QGIS

Connect QGIS to your PostGIS database; add candidate_final as a layer. Symbolise candidates by area (graduated). Add base map (OSM) and context layers (roads, clinics, protected areas). Produce a print layout (use your template from Lab 5.5).

For a collaborative review, export candidate_final plus the roads, clinics, and protected-area context layers to GeoJSON and upload them to Atlas. Style candidates by rank or area, configure popups with the scoring fields, and share the map link with someone acting as the city stakeholder. Their questions will often reveal missing context or unclear criteria.

Step 8 — Write up

In your lab notes:

  • How many parcels passed each filter?
  • Which single criterion eliminated the most candidates?
  • What would change if the buffer distances changed by ±50 %?
  • Which ranked candidate would you recommend? Justify.

Troubleshooting

  • Slow buffers — large ST_Union(ST_Buffer(...)) over thousands of roads can take time. Consider reducing to the study area first, or running once and caching the buffer layer.
  • Empty result — tighten criteria progressively to see where the funnel breaks. Often one criterion is too strict.
  • Invalid geometriesUPDATE parcels SET geom = ST_MakeValid(geom) before starting.
  • CRS mismatch — reproject everything to a common metric CRS (e.g., UTM) up front.

Self-check exercises

1. Why build the road buffer as a single union rather than keeping per-road buffers?

A single unioned buffer simplifies the subsequent ST_Intersects test — one geometry rather than thousands. It also avoids counting a parcel multiple times if it's within 500 m of several roads. The union also saves index space and speeds repeated queries.

2. Which step would you parallelise first if the city had 1 million parcels?

Step 4 / 5 — the filter against a big unioned geometry. With partitioning by tile or by administrative district, each partition can be evaluated independently. PostGIS can parallelise ST_Intersects joins if parallel_workers_per_gather is set. Beyond that, GeoPandas with Dask or Spark + Sedona handle truly huge parcel counts.

3. You want to add a sixth criterion — "within 400 m of a bus stop". How does your query change?

Add a bus-stop buffer table similar to the road buffer, then add AND ST_Intersects(c.geom, bus_buffer.geom) to the candidate filter. The pattern is identical — every additional criterion is either an intersect (must overlap) or a difference (must not overlap) with a pre-computed buffered layer.

Summary

  • Site suitability chains buffers, intersects, and differences to progressively narrow candidates.
  • Every criterion is a layer; combining layers answers the composite question.
  • The same pattern generalises to retail site selection, utility routing, conservation prioritisation.

Further reading

  • Malczewski, J. — GIS-Based Land-Use Suitability Analysis: A Critical Overview.
  • McHarg, I. — Design with Nature (foundational vision for overlay).
  • Esri — Site Suitability Modeling tutorial.
  • Geocomputation with R — landscape ecology chapter.
Module test

Module 9: Vector Spatial Analysis

Answer these quick multiple-choice questions to check your understanding before moving on.

1. What does a buffer create?
2. Which operation combines overlapping polygons into a single geometry?
3. Overlay analysis is used to understand what?