Skip to content
Geo Utilities

Spatial Join (Point in Polygon)

Join a Point layer against a Polygon layer — attach zone attributes to points and aggregate counts/numeric fields per zone.

How to use
  1. Paste or upload a Points GeoJSON layer and a Polygon/MultiPolygon GeoJSON layer (zones, districts, service areas, ...).
  2. Choose whether a point exactly on a zone's boundary counts as inside, how to handle a point inside more than one zone, and which numeric point fields to sum/average per zone.
  3. Check the map (green = matched, red = unmatched) and the zone summary table, then download the points-with-zone-attributes, zone-aggregates, or unmatched-points GeoJSON.
  • This tool supports exactly Point-in-Polygon containment — not line/polygon intersection or any other spatial predicate.
  • An empty zone shows a point count of 0, and a numeric summary of "—" (no data) rather than 0 — those mean different things.
  • Each layer is capped at 1000 features for this tool.

This tool supports exactly one geometry combination and predicate: a Point layer tested for containment inside a Polygon/MultiPolygon layer. It is not a general spatial join for other geometry pairs (line-in-polygon, polygon-overlap, etc.).

3 feature(s) parsed.

2 feature(s) parsed.

Map Preview

Loading map…

Blue = polygons. Green points matched a zone; red points matched none.

Zone summary

ZonePoints
District 11
District 21

1 of 3 point(s) matched no zone.

Code

Templated GeoPandas code mirroring this exact configuration — not AI-generated.

import geopandas as gpd

points_gdf = gpd.read_file("points.geojson")
polygons_gdf = gpd.read_file("polygons.geojson")

# includeBoundary=true on this tool's page — closest geopandas equivalent is predicate="intersects"
# ("within" excludes points exactly on a polygon's boundary; "intersects" counts them as inside).
joined = gpd.sjoin(points_gdf, polygons_gdf, how="left", predicate="intersects")

Each layer is capped at 1000 features for this tool.

Spatial Join (Point in Polygon) Coverage

Tests a Point layer for containment against a Polygon/MultiPolygon layer only — not line-in-polygon intersection, polygon-overlap, or any other spatial predicate. Whether a point exactly on a zone's boundary counts as inside is an explicit choice, not a silent default.

Per-zone results report a point count plus sum/mean/min/max for any numeric point fields you pick. A zone with zero matched points shows a count of 0 and 'no data' (not 0) for its numeric stats — those two are kept visibly distinct rather than collapsed into the same 0.

Frequently asked questions

What happens when a point falls inside more than one polygon?

By default it's attached to every matching polygon, which can double-count a point across overlapping zones' totals — switch to "first match only" to attach it to just the first matching polygon in the layer's input order instead.

Why does an empty zone show a dash instead of 0 for its stats?

Showing 0 for both "no points matched" and "the matched points summed to zero" would make those two very different situations indistinguishable — this tool reports them differently on purpose.

Report an issue