ggplot-rs 0.16.0

A Rust implementation of ggplot2's Grammar of Graphics
Documentation
# ggplot-rs in the browser (WASM) + DuckDB-Wasm spatial

**▶ Live: <https://sipemu.github.io/ggplot-rs/>** (auto-deployed from `main`).

Two interactive dashboards, all client-side (DuckDB-Wasm with the `spatial`
extension + ggplot-rs compiled to WebAssembly):

1. **World choropleth** — DuckDB reads **Natural Earth** countries and
   `ST_AsText`s the geometry to WKT; ggplot-rs renders an SVG. Hover for a
   country's population; **click a country to re-query DuckDB and zoom to its
   continent** (⟳ World resets).
2. **Live earthquakes** — DuckDB reads the USGS *past-30-days* GeoJSON feed and
   ggplot-rs colours the quakes by magnitude; the points trace the tectonic
   plate boundaries.
3. **Linked views** — a 100k-point scatter drawn by the raster (`canvas`)
   backend; **drag to brush** — the selected points stay bright while the rest
   fade, and a ggplot-rs bar chart updates with the per-group counts in your
   selection. Two ggplot-rs plots, linked in JS.

![World choropleth](../assets/gallery/world.png)

*(The screenshot above is the exact same render, produced natively by the CLI
from the identical DuckDB query — the browser path is byte-for-byte the same
`render_svg_native`.)*

## Build & run

```sh
# 1. Build the ggplot-rs WASM bundle (needs wasm-pack + the wasm32 target)
wasm-pack build crates/ggplot-rs-wasm --target web --out-dir ../../web/pkg --out-name ggplot_rs

# 2. Serve this directory over HTTP (module workers require it)
python3 -m http.server -d web 8080
# open http://localhost:8080
```

The bundle is ~310 KB of `.wasm` (no polars, no plotters — it uses the
plotters-free `SvgBackend`). `web/pkg/` is a build artifact and is git-ignored.

## How it fits together

```
DuckDB-Wasm (data + spatial)              ggplot-rs WASM (grammar + SVG)
  ST_Read(...) / ST_AsText(geom)  ──►  render_geo({ geometry, fill, label, … })
  (shapefile, GeoJSON, GeoPackage)         → <svg> with <title> hover tooltips
```

`render_geo(specJson) -> String` (see `crates/ggplot-rs-wasm/src/lib.rs`) takes columnar geometry +
options and returns an SVG document. Every mark is a real DOM element, so hover
works via the native `<title>` tooltip plus a little CSS.

## Scaling to many points

SVG is great up to ~10k–50k elements. For larger data, **aggregate in DuckDB**
(`GROUP BY`, hex-binning, `ST_` clustering, sampling) before rendering — DuckDB
crunches millions of rows client-side and ggplot-rs draws the compact summary.
For raw million-point scatter, a canvas/WebGL `DrawBackend` would be the next
step (the backend trait is designed for it).

## Real data

Swap the demo query's `VALUES` for a file read:

```sql
SELECT ST_AsText(geom) AS geometry, name, pop_est
FROM ST_Read('https://.../ne_110m_admin_0_countries.geojson')
```