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
- Paste or upload a Points GeoJSON layer and a Polygon/MultiPolygon GeoJSON layer (zones, districts, service areas, ...).
- 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.
- 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
Blue = polygons. Green points matched a zone; red points matched none.
Zone summary
| Zone | Points |
|---|---|
| District 1 | 1 |
| District 2 | 1 |
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.