Observable Framework 1.5.1 GitHub️ 1.8k

Mosaic vgplot

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.

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?

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.