Observable Plot
Expert guidance for building concise, exploratory data visualizations with Observable Plot
You are an expert in creating data visualizations with Observable Plot. ## Key Points - **Transforms**: Built-in data transforms like `Plot.binX`, `Plot.groupX`, `Plot.stackY`, `Plot.normalizeY`, and `Plot.windowY` for on-the-fly aggregation without preprocessing. - **Compound Marks**: Use `Plot.boxY` for box plots, `Plot.hexbin` for hexagonal binning, and `Plot.contour` for density contours. - **Interactions**: Use `Plot.tip` to add interactive tooltips and `Plot.crosshair` for crosshair annotations on hover. - **Projections**: Use the `projection` option (e.g., `"albers-usa"`, `"mercator"`) with `Plot.geo` for geographic maps. - **Marks as Annotations**: Use `Plot.ruleX`, `Plot.ruleY`, `Plot.text`, and `Plot.arrow` to annotate charts with reference lines and labels. - Let Plot infer scales and axes from the data rather than manually configuring them; override only when needed. - Use built-in transforms (`binX`, `groupX`, `stackY`) instead of pre-aggregating data, which keeps code concise and declarative. - In React, always clean up the chart in the `useEffect` return function to prevent DOM node leaks. - Forgetting that `Plot.plot()` returns a raw DOM element (SVG), not a React component; you must use a ref to append it to the DOM in React. - Confusing mark orientation: `Plot.barY` draws vertical bars (y encodes the quantitative value), while `Plot.barX` draws horizontal bars. Mixing them up swaps the axes. ## Quick Example ```bash npm install @observablehq/plot ``` ```html <script type="module"> import * as Plot from "https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm"; </script> ```
skilldb get data-visualization-skills/Observable PlotFull skill: 171 linesObservable Plot — Data Visualization
You are an expert in creating data visualizations with Observable Plot.
Overview
Observable Plot is a high-level, concise JavaScript library for exploratory data visualization created by the team behind D3. It follows a grammar-of-graphics approach where you declare marks (bars, dots, lines, areas, rules, text) and Plot handles scales, axes, and legends automatically. Use Observable Plot when you want to quickly explore and visualize data with minimal code, especially for statistical and analytical charts.
Setup & Configuration
Install via npm:
npm install @observablehq/plot
Or use the CDN:
<script type="module">
import * as Plot from "https://cdn.jsdelivr.net/npm/@observablehq/plot@0.6/+esm";
</script>
Basic usage (renders an SVG element):
import * as Plot from "@observablehq/plot";
const data = [
{ month: "Jan", sales: 100 },
{ month: "Feb", sales: 120 },
{ month: "Mar", sales: 90 },
];
const chart = Plot.plot({
marks: [
Plot.barY(data, { x: "month", y: "sales", fill: "steelblue" })
]
});
document.getElementById("chart").append(chart);
React Integration
import * as Plot from "@observablehq/plot";
import { useRef, useEffect } from "react";
function MyChart({ data }) {
const containerRef = useRef();
useEffect(() => {
const chart = Plot.plot({
marks: [
Plot.dot(data, { x: "x", y: "y", fill: "category" })
]
});
containerRef.current.replaceChildren(chart);
return () => chart.remove();
}, [data]);
return <div ref={containerRef} />;
}
Core Patterns
Dot / Scatter Plot
Plot.plot({
marks: [
Plot.dot(data, { x: "weight", y: "height", stroke: "species" }),
Plot.frame()
],
color: { legend: true }
});
Line Chart
Plot.plot({
marks: [
Plot.lineY(data, { x: "date", y: "price", stroke: "symbol" }),
Plot.ruleY([0])
],
y: { grid: true }
});
Histogram
Plot.plot({
marks: [
Plot.rectY(data, Plot.binX({ y: "count" }, { x: "age", fill: "steelblue" })),
Plot.ruleY([0])
]
});
Faceted Charts
Plot.plot({
facet: { data, x: "region" },
marks: [
Plot.barY(data, { x: "product", y: "sales", fill: "product" })
],
marginLeft: 60
});
Grouping and Aggregation
Plot.plot({
marks: [
Plot.barY(data, Plot.groupX({ y: "sum" }, { x: "category", y: "revenue", fill: "category" }))
]
});
Advanced Features
- Transforms: Built-in data transforms like
Plot.binX,Plot.groupX,Plot.stackY,Plot.normalizeY, andPlot.windowYfor on-the-fly aggregation without preprocessing. - Compound Marks: Use
Plot.boxYfor box plots,Plot.hexbinfor hexagonal binning, andPlot.contourfor density contours. - Interactions: Use
Plot.tipto add interactive tooltips andPlot.crosshairfor crosshair annotations on hover. - Projections: Use the
projectionoption (e.g.,"albers-usa","mercator") withPlot.geofor geographic maps. - Marks as Annotations: Use
Plot.ruleX,Plot.ruleY,Plot.text, andPlot.arrowto annotate charts with reference lines and labels.
Best Practices
- Let Plot infer scales and axes from the data rather than manually configuring them; override only when needed.
- Use built-in transforms (
binX,groupX,stackY) instead of pre-aggregating data, which keeps code concise and declarative. - In React, always clean up the chart in the
useEffectreturn function to prevent DOM node leaks.
Core Philosophy
Observable Plot is designed for the analyst, not the dashboard developer. Its grammar-of-graphics approach -- declare marks, let the library infer scales and axes -- optimizes for the speed of going from a question about data to a visual answer. You should be able to see a distribution, compare groups, or spot a trend in one or two lines of code. If you are spending more time configuring Plot than thinking about data, you are likely overriding defaults that were already correct.
The built-in transforms (binX, groupX, stackY, normalizeY, windowY) are a core part of the API, not a convenience add-on. They allow you to aggregate, bin, and reshape data inside the plot specification rather than in a separate preprocessing step. This keeps the visualization self-contained: the Plot call describes both the data transformation and the visual encoding in one declaration. Prefer transforms over pre-aggregating data; it makes the code shorter and keeps the raw data available for other marks in the same plot.
Plot returns a raw DOM element (an SVG node), not a React component or a framework-specific widget. In vanilla JavaScript, you append it to the page. In React, you use a ref and useEffect. In both cases, you are responsible for cleanup when the data or component changes. This design keeps Plot framework-agnostic but requires you to understand the DOM lifecycle in your specific context.
Anti-Patterns
-
Pre-aggregating data that transforms could handle: Computing group sums, bins, or cumulative values in JavaScript before passing data to Plot, when
Plot.groupX,Plot.binX, orPlot.windowYwould do it declaratively. This duplicates logic and makes the plot harder to modify. -
Over-configuring scales and axes: Manually setting scale domains, axis tick counts, and label formats when Plot's automatic inference would produce the same or better result. Override defaults only when the inferred behavior is wrong for your data.
-
Treating Plot as a React component: Rendering
Plot.plot()directly in JSX or expecting it to respond to React state changes. Plot returns a DOM node; in React you must use a ref, callPlot.plot()insideuseEffect, and clean up the previous node on re-render. -
Confusing mark orientation: Using
Plot.barYwhen horizontal bars are intended (which should bePlot.barX), or vice versa. The Y/X suffix indicates which axis encodes the quantitative value, not the direction the bars face. -
Building dashboards with Plot: Attempting to use Observable Plot for production dashboards with real-time updates, complex interactivity, and coordinated views. Plot is optimized for exploratory, static-ish analysis charts. For interactive dashboards, use a library designed for that purpose.
Common Pitfalls
- Forgetting that
Plot.plot()returns a raw DOM element (SVG), not a React component; you must use a ref to append it to the DOM in React. - Confusing mark orientation:
Plot.barYdraws vertical bars (y encodes the quantitative value), whilePlot.barXdraws horizontal bars. Mixing them up swaps the axes.
Install this skill directly: skilldb add data-visualization-skills
Related Skills
Chart Js
Expert guidance for building responsive charts quickly with Chart.js
D3
Expert guidance for building custom, data-driven visualizations with D3.js
Echarts
Expert guidance for building feature-rich interactive charts with Apache ECharts
Nivo
Expert guidance for building rich, themed data visualizations in React with Nivo
Plotly
Expert guidance for building interactive, publication-quality charts with Plotly.js
Recharts
Expert guidance for building declarative React charts with Recharts