Skip to content

Commit 8f4c254

Browse files
authored
docs(#294): recommend exact SUM(h3_cell_area()) over nominal per-cell constant (#295)
H3 cells are not equal-area; the nominal per-resolution constant is a global average and undercounts region areas by well over 5% at the extremes (~6.6% for California's res-8 grid). Update the human-facing README and datasets guide to lead with exact SUM(h3_cell_area(hN,'km^2')) over distinct cells, demoting the count x constant path to the unscoped-global fallback it is. Matches h3-guide.md (the app-facing guidance, already correct). The STAC- description root cause is tracked separately in boettiger-lab/data-workflows#389.
1 parent 3a14ff8 commit 8f4c254

2 files changed

Lines changed: 19 additions & 7 deletions

File tree

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ If every pod's imageID matches the pinned digest, prod is current and consistent
222222
## Query Optimization Tips
223223

224224
1. **Always include h0 in joins** - Enables partition pruning for 5-20x speedup
225-
2. **Use APPROX_COUNT_DISTINCT(h8)** - Fast area calculations with H3 hexagons
225+
2. **Compute areas with `SUM(h3_cell_area(h8, 'km^2'))`** - Exact per-cell area over distinct cells (H3 cells are not equal-area)
226226
3. **Filter small tables first** - Create CTEs to reduce join cardinality
227227
4. **Set THREADS=100** - Parallel S3 reads are I/O bound, not CPU bound
228228
5. **Enable object cache** - Reduces redundant S3 requests
@@ -233,10 +233,10 @@ See [query-optimization.md](query-optimization.md) for detailed guidance.
233233

234234
All datasets use Uber's [H3 hexagonal grid system](https://h3geo.org) for spatial indexing:
235235

236-
- Resolution 8 (h8): ~0.737 km² per hex
236+
- Resolution 8 (h8): ~0.74 km² per hex (nominal; true cell area varies ~0.55–0.82 km²)
237237
- Resolution 0-4 (h0-h4): Coarser resolutions for global analysis
238238
- Use `h3_cell_to_parent()` to join datasets at different resolutions
239-
- Use `APPROX_COUNT_DISTINCT(h8) * 0.737327598` to calculate areas in km²
239+
- Compute areas with `SUM(h3_cell_area(h8, 'km^2'))` over distinct cells — exact at any resolution. Multiplying a hex count by a nominal per-cell constant is a global-average approximation only, suitable for unscoped global aggregates. See [h3-guide.md](h3-guide.md).
240240

241241
## Testing
242242

docs/guide/datasets.md

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,25 @@ All datasets are indexed using [Uber's H3 hexagonal grid system](https://h3geo.o
3434

3535
### Area calculations
3636

37+
H3 cells are **not** equal-area — true cell area varies with latitude and
38+
icosahedral distortion (res-8 cells range ~0.55–0.82 km²), so a nominal
39+
per-resolution constant introduces a systematic error (~6% for California).
40+
For a region, feature, or per-group area, sum the **exact** per-cell area over
41+
**distinct** cells:
42+
3743
```sql
38-
-- Area in km² using H3 hex counts
39-
SELECT APPROX_COUNT_DISTINCT(h8) * 0.737327598 AS area_km2
40-
FROM read_parquet('s3://...')
41-
WHERE ...
44+
-- Exact area in km² (the proper method)
45+
SELECT SUM(h3_cell_area(h8, 'km^2')) AS area_km2
46+
FROM (SELECT DISTINCT h8, h0 FROM read_parquet('s3://...') WHERE ...);
4247
```
4348

49+
Only for unscoped global aggregates over millions of cells — where
50+
materializing every distinct cell would defeat the fast approximate path — fall
51+
back to multiplying an approximate count by the nominal constant
52+
(`APPROX_COUNT_DISTINCT(h8) * 0.737327598`, accurate to ~1–2% globally).
53+
54+
See [h3-guide.md](../../h3-guide.md) for the full area guidance.
55+
4456
### Cross-dataset joins
4557

4658
Always include `h0` in join conditions to enable partition pruning:

0 commit comments

Comments
 (0)