agentsclimarketplace

Carto hotspot analysis

Skill CartoDB/agent-skills/skills/carto-hotspot-analysis

Builds Getis-Ord Gi* hotspot analysis workflows in CARTO. Triggers when the user mentions hotspots, coldspots, spatial clusters, Getis-Ord, Gi*, cluster detection, concentration areas, "where do X cluster", spacetime hotspot, temporal clusters, time-varying patterns, hotspot trends, emerging hotspots, Mann-Kendall, or wants to find statistically significant spatial or spatiotemporal patterns in point or grid data.From its SKILL.md

Install
npx -y skills add CartoDB/agent-skills --skill carto-hotspot-analysis

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 6 stars6 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

9.1 KB, as published. Nobody here has run it

Hotspot Analysis with Getis-Ord Gi*

Builds CARTO Workflows that identify statistically significant spatial clusters (hotspots and coldspots) using the Getis-Ord Gi* statistic.

Prerequisites: Load carto-create-workflow for the development process, JSON structure, and validation commands.


Instructions

A hotspot workflow always follows this pipeline:

Source Data → (Filter) → Spatial Indexing → Aggregation → Getis-Ord Gi* → (Filter Significant) → Save

Step 1: Load Source Data

Use native.gettablebyname. The input table typically contains point geometries.

Success: Node outputs a table with a geometry column (e.g. geom).

Step 2: Filter (if needed)

Use native.wheresimplified or native.where to narrow the dataset before analysis (e.g. filter by category, date range, non-null values).

Success: Output contains only the subset relevant to the analysis.

Step 3: Build a Complete Grid

Preferred approach: First polyfill the study area boundary (e.g. district polygons) with native.h3polyfill to create a complete, gap-free grid. Then enrich this grid with the data to analyze (e.g. count points per cell via native.h3enrich or a manual join + group by). This ensures every cell in the study area has a value (even if 0), which Getis-Ord needs — gaps in the grid distort the neighborhood calculations and can produce misleading results.

Simpler alternative (when no study area boundary is available): Convert point geometries directly to grid cells with native.h3frompoint or native.quadbinfromgeopoint. Be aware this only produces cells where data exists, leaving gaps that may affect the statistic.

Resolution guidance — higher resolution = smaller cells = more local patterns:

ResolutionCell sizeUse case
H3 res 7~5 km edgeDistrict/city-level patterns
H3 res 8~2 km edgeNeighborhood-level
H3 res 9~500m edgeStreet-level

Success: A contiguous grid covering the study area, with every cell assigned a spatial index column (e.g. h3).

Step 4: Aggregate per Cell

Use native.groupby to produce one row per cell with a numeric value:

  • Group by: the spatial index column (h3)
  • Aggregation: h3,count (or value_col,sum / value_col,avg)

If using the polyfill approach, cells with no data should have a value of 0 (use COALESCE(count, 0) via native.selectexpression after joining).

Success: Output has exactly one row per unique cell with a count/sum column — no gaps.

Step 5: Run Getis-Ord Gi*

Use native.getisord with:

InputDescriptionDefault
indexcolColumn with H3/Quadbin indexesh3
valuecolNumeric column to analyzeh3_count
kernelWeighting function for neighborsuniform
sizeK-ring size (neighborhood radius in hops)3

Kernel options: uniform, triangular, quadratic, quartic, gaussian. Default to uniform (equal weight to all neighbors) unless the user has a reason to decay weight with distance.

K-ring size: Larger = smoother, broader patterns. Smaller = more localized clusters.

Success: Output contains index, gi (z-score), and p_value columns for every cell. (See the Provider casing note in Gotchas — Snowflake surfaces these UPPERCASE.)

Step 6: Filter Significant Results (optional)

Use native.where to keep only statistically significant cells:

  • p_value < 0.05 — 95% confidence
  • p_value < 0.05 AND gi > 0 — hotspots only
  • p_value < 0.05 AND gi < 0 — coldspots only

Success: Only cells with statistically meaningful clustering remain.

Step 7: Save

Use native.saveastable to persist results. The H3/Quadbin column is directly visualizable in CARTO Builder without geometry conversion.

Success: Validated workflow that can be uploaded via carto workflows create.


Output Columns

ColumnMeaning
indexSpatial index cell ID (H3 or Quadbin)
giGi* z-score — positive = hotspot, negative = coldspot
p_valueStatistical significance — lower = more confident

The engine declares these lowercase. See the Provider casing note in Gotchas for Snowflake.


Gotchas

  • Provider casing & SQL dialect. This skill documents columns in lowercase (BigQuery / Databricks / Postgres / Redshift convention). On Snowflake, unquoted identifiers surface UPPERCASE — reference H3, INDEX, GI, P_VALUE, H3_COUNT in expressions. For dialect-specific SQL fragments (e.g. DATETIME_TRUNC below), see carto-create-workflow/references/providers/<provider>.md for the equivalents table.
  • The Getis-Ord component requires the Analytics Toolbox. Always run carto workflows verify-remote --connection <conn> to ensure the AT path is resolved. carto workflows validate is offline and cannot resolve AT location.
  • The output column is named index, not h3 or quadbin. If you need to join back to original data, rename it (e.g. with native.renamecolumn).
  • If you call native.h3boundary to materialize cell geometries for visualization, the new column is named <h3col>_geo (e.g. index_geo), not geom. Reference it accordingly in downstream nodes.
  • The valuecol must be numeric. If you're counting features, the group-by step must produce a count column — don't pass the raw index column as the value.
  • Resolution too high + large area = very many cells, which can be slow or hit memory limits. Start with a moderate resolution and refine.
  • An empty result from the filter step (Step 6) usually means the k-ring size is too small or the data is too sparse for significant clustering. Try increasing size or lowering the resolution.
  • Date columns must be DATETIME type for spacetime Getis-Ord. CAST if your data has DATE or TIMESTAMP.
  • Temporal bandwidth choice dramatically affects results. bandwidth=1 detects rapid changes; bandwidth=3+ smooths over longer trends.
  • For time-series clustering, pre-filter to only significant cells (the 60% heuristic) to avoid clustering noise.
  • The spacetime classification component runs internally on the Gi* output -- do NOT filter by p_value before classification, or the trend test will have incomplete data.

Spacetime Variants

Getis-Ord Spacetime (native.getisordspacetime):

  • Extends basic Gi* to detect clusters in both space AND time.
  • Additional inputs: kerneltime (uniform/gaussian), bandwidth (number of time steps), timeinterval (week/month/day).
  • Data must be pre-aggregated into time bins (e.g. weekly counts per H3 cell).
  • Pipeline: points -> H3 -> create time column (BigQuery: DATETIME_TRUNC(CAST(datetime AS TIMESTAMP), WEEK); Snowflake / Databricks / Postgres: DATE_TRUNC('WEEK', datetime)) -> GROUP BY (h3, time_bin) -> Getis-Ord Spacetime -> filter p_value < 0.05 AND gi > 0.

Spacetime Hotspot Classification (native.spacetimehotspotsclassification):

  • Chains AFTER Getis-Ord Spacetime output.
  • Classifies each cell's temporal trend: new hotspot, consecutive, intensifying, diminishing, sporadic, oscillating, historical.
  • Uses Modified Mann-Kendall trend test with a significance threshold (default 0.05).
  • Pipeline: ... -> Getis-Ord Spacetime -> Spacetime Hotspots Classification.

Time Series Clustering (native.timeseriesclustering):

  • Groups locations by similarity of their temporal Gi* pattern.
  • Chain: Getis-Ord Spacetime -> filter significant cells -> Cluster Time Series.
  • Method: profile (shape-based) or value (magnitude-based).
  • Filtering heuristic from the template: keep cells where >=60% of time steps have p_value < 0.05.

Reference Templates

These files are working examples (skill-local files in hotspot-analysis/, others in the project root):

FileDescription
poi_hotspot.jsonStockholm amenity POIs — H3 res 9, uniform kernel, k=3
space_time_hotspot.jsonBarcelona accidents — spacetime Gi*, H3 res 9, weekly bins
spacetime_hotspot_classification.jsonLondon collisions — spacetime Gi* + classification, gaussian kernel

Common Variations

VariantHow
Polygon input instead of pointsUse native.h3polyfill instead of native.h3frompoint
Enrich existing gridUse native.h3enrich to count points into a grid (avoids manual group-by + join)
Combine with other dataJoin Getis-Ord output with enrichment or attribute tables before saving
Spacetime hotspotsUse native.getisordspacetime — see Spacetime Variants section above
Classify hotspot trendsUse native.spacetimehotspotsclassification — chains after spacetime Gi* output

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.