Observable Plot

repository·main·Indexed 26 days ago

https://github.com/observablehq/plot

A JavaScript library for rapid, expressive data visualization of tabular data following the grammar of graphics paradigm. It provides a variety of marks including dot, image, geo, and density, along with support for geographic projections, window transforms, and complex faceting. Version 0.6.17 supports features such as color and opacity legends, custom render functions in marks, and server-side rendering via a custom document option.

Tokens
81K
Snippets
282
Records
515
Agent score
89%

What's inside @observablehq/plot

  1. Overview of Observable Plot

    main
    Observable Plot is an open-source JavaScript library designed for visualizing tabular data and accelerating exploratory data analysis. It uses a grammar of graphics approach, allowing you to create visualizations by assigning data columns to visual properties of marks (such as position, color, or size) using scales and layered marks.
  2. Understand Plot Transforms

    main

    Transforms derive data as part of the plot specification, helping to reshape data for visualization (e.g., calculating medians, binning, or rolling averages).

    Key characteristics:

    • Not required: You can aggregate data manually using libraries like D3 and pass the results to marks.
    • Two-argument pattern: Most built-in transforms take two arguments: options (transform-specific settings) and mark options (settings to be passed through to the mark). The transform returns a new options object containing the transformed mark options.
    • Composability: Transforms can be nested. For example, you can apply a normalize transform on top of a bin transform.
    • Implicit transforms: Many marks have built-in transforms. For example, rectY applies an implicit stackY transform when using the y option.
  3. Understand Scales in Observable Plot

    main

    Scales convert abstract data values (like time, temperature, or categories) into visual values (like x and y positions, color, radius, or opacity).

    In Plot, marks bind data channels to scales. While channel names often match scale names (e.g., the x channel uses the x scale), they can differ (e.g., an area mark's y1 and y2 channels both bind to the y scale). You can also use scale overrides to opt-out of a default scale for a specific channel.

    Key concepts:

    • Domain: The input abstract values (e.g., a date range [start, end] or a set of categories ['A', 'B']).
    • Range: The output visual values (e.g., pixel positions [left, right] or a color extent ['blue', 'red']).
    • Type: The nature of the input data (e.g., linear or ordinal).
  4. Core Concepts of Observable Plot

    main

    Observable Plot is a JavaScript library designed for exploratory data visualization. Unlike traditional charting libraries that use predefined chart types, Plot uses a layered approach based on geometric shapes called Marks.

    Key concepts include:

    • Marks: Layered geometric shapes (e.g., bars, dots, lines) used to build visualizations.
    • Scales: Functions that map abstract data values (like time or temperature) to visual values (like position or color).
    • Transforms: On-the-fly data derivations, such as binning quantitative values or computing rolling averages.
    • Facets: The use of small multiples to repeat a plot across different partitions of data for easier comparison.
    • Projections: Support for GeoJSON and D3's spherical projection system for geographic mapping.
  5. Use built-in intervals in Plot

    main

    Observable Plot provides built-in interval implementations that can be used with the tick option for scales, the thresholds option for bin transforms, or other purposes.

    Intervals implement several core methods:

    • floor(value): Returns the greatest interval boundary less than or equal to the specified value.
    • offset(value, [step]): Returns the value equal to value plus step intervals (defaults to 1).
    • range(start, stop): Returns an array of values representing every interval boundary from start (inclusive) to stop (exclusive).
    • ceil(value): Returns the least interval boundary greater than or equal to the specified value.
  6. Use the select transform to filter marks

    main

    The select transform filters a mark's index to show a subset of the data, typically used to pull a single value or a sample subset out of each series (e.g., labeling the last point in a line chart).

    Important: The transform uses input order, not natural order by value, to determine first and last. For example, if a dataset is in reverse chronological order, the 'first' element is the most recent.

    To group data into series, use the z, fill, or stroke channels in the same way as area or line marks.

    Plot.plot({
      y: {grid: true},
      marks: [
        Plot.ruleY([0]),
        Plot.line(aapl, {x: "Date", y: "Close"}),
        Plot.text(aapl, Plot.selectLast({x: "Date", y: "Close", text: "Close", frameAnchor: "bottom", dy: -6}))
      ]
    })
  7. Use the Tip mark for interactive or static annotations

    main

    The Plot.tip mark displays text or name-value pairs in a floating box anchored to an (x, y) position.

    It can be used in two primary ways:

    1. Interactive Tips: Paired with a pointer transform (like Plot.pointerX or Plot.pointer) to reveal details when hovering over data points.
    2. Static Annotations: Used to draw attention to specific points by providing fixed coordinates and a title channel.

    By default, if multiple tips and pointer transforms are present, the pool option is true, meaning only one tip is visible at a time. Set pool: false to allow multiple tips to be visible simultaneously.

    // Interactive example using pointerX
    Plot.plot({
      y: {grid: true},
      marks: [
        Plot.lineY(aapl, {x: "Date", y: "Close"}),
        Plot.tip(aapl, Plot.pointerX({x: "Date", y: "Close"}))
      ]
    })
    
    // Static annotation example
    Plot.plot({
      y: {grid: true},
      marks: [
        Plot.lineY(aapl, {x: "Date", y: "Close"}),
        Plot.tip(
          [`Apple stock reaches a new high of $133 on Feb. 23, 2015.`],
          {x: new Date("2015-02-23"), y: 133, dy: -3, anchor: "bottom"}
        )
      ]
    })
  8. Use the Window transform for rolling statistics

    main

    The window transform is a specialized map transform used to compute moving windows and derive summary statistics (like rolling averages, minimums, or maximums) from them. It can be applied to specific channels using Plot.windowX or Plot.windowY, or used generally with Plot.window inside a Plot.map call.

    Note that the transform uses the input order of the data to determine the window alignment, not the natural value order. If your data is not sorted chronologically, use a sort transform first.

    Plot.plot({
      y: {
        grid: true,
        label: "Temperature (°F)"
      },
      marks: [
        Plot.areaY(sftemp, {x: "date", y1: "low", y2: "high", fillOpacity: 0.3}),
        Plot.lineY(sftemp, Plot.windowY(k, {x: "date", y: "low", stroke: "blue"})),
        Plot.lineY(sftemp, Plot.windowY(k, {x: "date", y: "high", stroke: "red"}))
      ]
    })
  9. Use the density mark

    main

    The Plot.density mark shows the estimated density of two-dimensional or one-dimensional point clouds using contours (isolines). It is useful for visualizing concentrations in dense datasets to avoid overplotting.

    Key Features:

    • 2D Density: Visualizes concentrations of $(x, y)$ points.
    • 1D Density: Visualizes the distribution of a single dimension (e.g., just $x$).
    • Projections: Supports Plot's projection system (e.g., for geographic density maps).
    • Color Encoding: Using the keyword density for stroke or fill creates a sequential color encoding based on density values.
    • Faceting: Supports fx and fy for comparison across facets. Thresholds are automatically synchronized to the series with the highest density to facilitate comparison.
    Plot.plot({
      marks: [
        Plot.density(data, {x: "waiting", y: "eruptions", stroke: "blue"})
      ]
    })
  10. Use the tip mark for interactive details

    main

    The Plot.tip mark displays text or name-value pairs in a floating box anchored to a position. It is designed to work with pointer interactions so that only the point closest to the pointer is rendered, allowing users to reveal details by hovering.

    Implicit Tip

    You can enable an implicit tip mark by setting tip: true on a mark option:

    Plot.lineY(data, {x: "Date", y: "Close", tip: true}).plot()

    Explicit Tip

    For more control, use Plot.tip as a separate mark. You can pair it with Plot.pointerX or Plot.pointerY to find the closest point:

    Plot.plot({
      marks: [
        Plot.lineY(data, {x: "Date", y: "Close"}),
        Plot.tip(data, Plot.pointerX({x: "Date", y: "Close"}))
      ]
    })

    Static Annotations

    You can also use Plot.tip for static commentary by providing an array of strings (for multi-line text) and an anchor position:

    Plot.tip(
      [`Your multi-line text here...`],
      {x: dateValue, y: value, dy: -3, anchor: "bottom"}
    )
    Plot.lineY(aapl, {x: "Date", y: "Close", tip: true}).plot()
  11. Work with GeoJSON data and property shorthand

    main

    As of version 0.6.16, all marks support GeoJSON data and property shorthand. When using a GeoJSON FeatureCollection, you can use a property name directly as a channel option (e.g., fill: "unemployment"), which is shorthand for (d) => d.properties.unemployment. Additionally, the geo mark now supports the tip: true option, which uses an implicit centroid transform to enable interactive tooltips.

    Plot.plot({
      projection: "albers-usa",
      color: {
        type: "quantile",
        n: 9,
        scheme: "blues",
        label: "Unemployment (%)",
        legend: true
      },
      marks: [
        Plot.geo(counties, {
          fill: "unemployment",
          title: (d) => `${d.properties.name} ${d.properties.unemployment}%`,
          tip: true
        })
      ]
    })
  12. Use the projection option in Plot

    main

    The projection plot option applies a two-dimensional projection in place of x and y scales. While typically used with geo marks to create maps, it can be used with any mark supporting x and y channels (e.g., dot, text, arrow, rect).

    For marks using x1, y1, x2, and y2 channels, the projection applies to both points. For other marks, it applies to the single x, y point.

    Supported built-in named projections include:

    • equirectangular (plate carrée)
    • orthographic
    • stereographic
    • mercator
    • equal-earth
    • azimuthal-equal-area
    • azimuthal-equidistant
    • conic-conformal
    • conic-equal-area
    • conic-equidistant
    • gnomonic
    • transverse-mercator
    • albers
    • albers-usa
    • identity
    • reflect-y (identity with y pointing up)
    • null (default, for pre-projected geometry)