Using Mosaic vgplot in the Observable framework for linked interactive visualizations.
Observable Framework documentation: Library: Mosaic vgplot Source: https://observablehq.com/framework/lib-mosaic
Mosaic is a system for linking data visualizations, tables, and inputs, leveraging DuckDB for scalable processing. Mosaic includes an interactive grammar of graphics, Mosaic vgplot, built on Observable Plot. With vgplot, you can interactively visualize and explore millions — even billions — of data points.
The example below shows the pickup and dropoff locations of one million taxi rides in New York City from Jan 1–3, 2010. The dataset is stored in a 8MB Apache Parquet file, generated with a data loader.
${maps}
${histogram}
The views above are coordinated: brushing a time window in the histogram, or a region in either map, will filter both maps. What spatial patterns can you find?
Mosaic vgplot is available by default in Markdown as vg and is backed by the default DuckDB client that is configured using SQL front matter. If you would prefer to initialize Mosaic yourself, you can do something like:
import {DuckDBClient} from "npm:@observablehq/duckdb";
import * as vgplot from "npm:@uwdata/vgplot";
const db = await DuckDBClient.of({trips: FileAttachment("nyc-taxi.parquet")});
const coordinator = new vgplot.Coordinator();
coordinator.databaseConnector(vgplot.wasmConnector({duckdb: db._db}));
const vg = vgplot.createAPIContext({coordinator});
The code below creates three views, coordinated by Mosaic’s crossfilter helper.
// Create a shared filter
const $filter = vg.Selection.crossfilter();
// Shared attributes for the maps
const attributes = [
vg.width(315),
vg.height(550),
vg.margin(0),
vg.xAxis(null),
vg.yAxis(null),
vg.xDomain([297000, 297000 + 28.36 * 315]),
vg.yDomain([57900, 57900 + 28.36 * 550]), // ensure aspect ratio of 1
vg.colorScale("symlog")
];
// Create two side-by-side maps
const maps = vg.hconcat(
vg.plot(
vg.raster(vg.from("trips", {filterBy: $filter}), {x: "px", y: "py", imageRendering: "pixelated"}),
vg.intervalXY({as: $filter}),
vg.text([{label: "Taxi pickups"}], {
dx: 10,
dy: 10,
text: "label",
fill: "white",
frameAnchor: "top-left"
}),
...attributes,
vg.colorScheme("turbo"),
vg.frame({stroke: "black"})
),
vg.hspace(10),
vg.plot(
vg.raster(vg.from("trips", {filterBy: $filter}), {x: "dx", y: "dy", imageRendering: "pixelated"}),
vg.intervalXY({as: $filter}),
vg.text([{label: "Taxi dropoffs"}], {
dx: 10,
dy: 10,
text: "label",
fill: "white",
frameAnchor: "top-left"
}),
...attributes,
vg.colorScheme("turbo"),
vg.frame({stroke: "black"})
)
);
// Create the histogram
const histogram = vg.plot(
vg.rectY(vg.from("trips"), {x: vg.bin("time"), y: vg.count(), insetLeft: 0.5, insetRight: 0.5}),
vg.intervalX({as: $filter}),
vg.yTickFormat("s"),
vg.xLabel("Hour of pickup"),
vg.yLabel("Number of rides"),
vg.width(640),
vg.height(100)
);
For more Mosaic examples, see the Mosaic + Framework website.
npx skills add spqw/observable-framework-lib-mosaic下载完整 Skill 目录,包含 SKILL.md 及所有相关文件
Search for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer