Public
Edited
Nov 29, 2023
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
grid: true,
height: 100,
x: {
label: "Date →"
},
y: {
ticks: false
},
marks: [
Plot.rect(CAREER, {
y1: (d) => d.layer,
y2: (d) => d.layer + 1,
x1: "start",
x2: "end",
fill: "color"
}),
Plot.text(CAREER, {
y: (d) => d.layer + 0.5,
x: "start",
text: "text",
fontSize: 13,
fill: "white",
textAnchor: "start"
}),
Plot.tickX(PREVIOUS_TALKS, {
channels: { name: "name" },
href: "url",
target: "_blank",
x: "date",
fill: "black",
tip: true
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Anscombe's quartet",
aspectRatio: 0.5,
facet: { data: anscombe, x: "series" },
marks: [
Plot.frame(),
Plot.dot(anscombe, { x: "x", y: "y" }),
Plot.linearRegressionY(anscombe, {
x: "x",
y: "y",
ci: 0,
stroke: "red"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
alphabet
Insert cell
Insert cell
Insert cell
bars = Plot.barY(alphabet, { x: "letter", y: "frequency", fill: "frequency" })
Insert cell
Insert cell
Insert cell
bars.channels
Insert cell
bars.channels.x.value.transform()
Insert cell
bars.channels.y2.value.transform()
Insert cell
Insert cell
barsPlot = bars.plot({
caption: "Letter frequencies",
color: { type: "linear", scheme: "cividis" }
})
Insert cell
Insert cell
Insert cell
barsPlot.scale("y")
Insert cell
[barsPlot.scale("y").apply(0), barsPlot.scale("y").apply(0.12702)]
Insert cell
Insert cell
barsPlot.scale("x")
Insert cell
barsPlot.scale("x").apply("E")
Insert cell
Insert cell
barsPlot.scale("color")
Insert cell
rgb = barsPlot.scale("color").apply(0.12702)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
md`${_.take(Object.keys(Plot), 24).map(
(k) => `- [${k}](https://observablehq.com/plot/marks/${k.toLowerCase()})\n`
)}`
Insert cell
Insert cell
Insert cell
stateCovidData
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Insert cell
covidPlot.scale("y")
Insert cell
covidPlot.scale("y").apply(10000)
Insert cell
covidPlot = Plot.plot({
caption: "Covid cases in New York",
grid: true,
marginLeft: 50,
y: { type: scaleOverride, label: "↑ Positive cases" },
width,
marks: [
Plot.ruleY([0]),
Plot.line(filteredCovidData, {
x: "date",
y: "positiveIncrease"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "The weight of a car is a good linear predictor of its power",
marks: [
Plot.dot(cars, {
x: "weight (lb)",
y: "power (hp)",
filter: (d, i) => i < m
}),
Plot.linearRegressionY(cars, {
filter: (d, i) => i < m,
x: "weight (lb)",
y: "power (hp)",
stroke: "red"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Heights and weights of Olympic athletes",
nice: true,
color: {
legend: true,
scheme: "Cividis"
},
marks: [
Plot.rect(
olympians,
Plot.bin(
{ fill: "count" },
{
filter: (d) => d.weight < weightThreshold,
x: "weight",
y: "height",
thresholds,
tip: true
}
)
),
Plot.ruleX([weightThreshold], { stroke: "red " }),
Plot.dot(olympians, {
filter: (d) => d.weight >= weightThreshold,
x: "weight",
y: "height",
opacity: 0.1,
fill: "black",
tip: true
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Distribution of weights of Olympic athletes",
color: {
legend: true,
scheme: "Cividis"
},
y: { grid: true },
marks: [
Plot.tickX(olympians, {
x: "weight",
strokeOpacity: 0.05,
filter: (d) => d.weight >= weightThreshold3
}),
Plot.ruleX([weightThreshold3], { stroke: "red " }),
Plot.rectY(
olympians,
Plot.binX(
{ y: "count", fill: "count" },
{
x: "weight",

filter: (d) => d.weight < weightThreshold3
}
)
),
Plot.ruleY([0])
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Heights and weights of Olympic athletes",
nice: true,
color: {
legend: true,
scheme: "Cividis"
},
marks: [
Plot.hexagon(
olympians,
Plot.hexbin(
{ r: "count", fill: "count" },
{
filter: (d) => d.weight < weightThreshold2,
x: "weight",
y: "height",
binWidth,
tip: true
}
)
),
Plot.ruleX([weightThreshold2], { stroke: "red" }),
Plot.dot(olympians, {
filter: (d) => d.weight >= weightThreshold2,
x: "weight",
opacity: 0.1,
y: "height",
fill: "black",
tip: true
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Chicago crash deaths",
style: "overflow: visible;",
caption: "Annual cumulative traffic deaths by day of years in Chicago",
y: {
grid: true,
label: "Deaths"
},
color: {
domain: [false, true],
range: ["#ccc", "red"]
},
marks: [
Plot.line(
chicagoCrashDeaths,
Plot.mapY("cumsum", {
x: (d) =>
new Date(2020, d.crash_date.getMonth(), d.crash_date.getDate()),
y: (d) => 1,
z: (d) => d.crash_date.getFullYear(),
stroke: (d) => new Date().getFullYear() === d.crash_date.getFullYear(),
curve: "step-before"
})
),
Plot.text(
chicagoCrashDeaths,
Plot.selectLast(
Plot.mapY("cumsum", {
x: (d) =>
new Date(2020, d.crash_date.getMonth(), d.crash_date.getDate()),
y: (d) => 1,
z: (d) => d.crash_date.getFullYear(),
text: (d) => d.crash_date.getFullYear().toString(),
textAnchor: "start",
dx: 3,
dy: -2
})
)
),
Plot.axisX({
ticks: "month",
tickSize: 16,
tickPadding: -11,
tickFormat: " %b",
textAnchor: "start"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Stock prices of major tech companies",
style: "overflow: visible;",
y: { grid: true },
marks: [
Plot.ruleY([0]),
Plot.line(stocks, { x: "Date", y: "Close", stroke: "Symbol" }),
Plot.text(
stocks,
Plot.selectLast({
x: "Date",
y: "Close",
z: "Symbol",
text: "Symbol",
textAnchor: "start",
dx: 3
})
)
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Distribution of Olympic athletes by sport",
marginBottom: 100,
x: { label: null, tickRotate: 90 },
y: { grid: true },
marks: [
Plot.barY(olympians, Plot.groupX({ y: "count" }, { x: "sport" })),
Plot.ruleY([0])
]
})
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Stock prices of major tech companies",
y: {
type: "log",
grid: true,
label: "Change in price (%)",
tickFormat: (
(f) => (x) =>
f((x - 1) * 100)
)(d3.format("+d"))
},
marks: [
Plot.ruleY([1]),
Plot.line(
stocks,
Plot.normalizeY({
x: "Date",
y: "Close",
stroke: "Symbol"
})
),
Plot.text(
stocks,
Plot.selectLast(
Plot.normalizeY({
x: "Date",
y: "Close",
z: "Symbol",
text: "Symbol",
textAnchor: "start",
dx: 3
})
)
)
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Crimean war casualties by cause",
y: { grid: true },
color: { legend: true },
marks: [
Plot.areaY(crimea, Plot.stackY({ x: "date", y: "deaths", fill: "cause" })),
Plot.ruleY([0])
]
})
Insert cell
Insert cell
Plot.plot({
caption: "Crimean war casualties by cause",
y: { grid: true },
color: { legend: true },
marks: [
Plot.areaY(crimea, { x: "date", y: "deaths", fill: "cause" }),
Plot.ruleY([0])
]
})
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Weights of cars",
height: 160,
marks: [
Plot.dotX(
cars,
Plot.dodgeY("middle", {
x: "weight (lb)",
tip: true,
title: "name",
fill: "currentColor"
})
)
]
})
Insert cell
Insert cell
Plot.ruleX(cars, { x: "weight (lb)" }).plot({ caption: "Weights of cars" })
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
caption: "Daily high and low temperature moving averages in San Francisco",
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" }))
]
})
Insert cell
Insert cell
Insert cell
o = olympians
Insert cell
o
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
Insert cell
Plot.plot({
caption: "Heights of Olympic athletes",
width: 400,
marks: [
Plot.tickY(olympians, {
y: "height",
stroke: "sex",
strokeOpacity: 0.01,
strokeWidth: 2,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES,
tip: true
})
]
})
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
width,
marks: [
Plot.dot(
_.sampleSize(olympians, 2000),
Plot.dodgeX("middle", {
y: "height",
fill: "sex",
sort: "sex",
padding: -1,
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES
})
)
]
})
Insert cell
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
width: 400,
marks: [
Plot.tickY(olympians, {
y: "height",
x: "sex",
stroke: "sex",
strokeWidth: 2,
strokeOpacity: 0.02,
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES
})
]
})
Insert cell
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
color: { legend: true },
marks: [
Plot.rectX(
olympians,
Plot.binY(
{ x: "count" },
{
y: "height",
fill: "sex",
tip: true
}
)
),
Plot.ruleX([0])
]
})
Insert cell
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
color: { legend: true },
marks: [
Plot.rectX(
olympians,
Plot.binY(
{ x: "count" },
{ y: "height", fill: "sex", fx: "sex", tip: true }
)
),
Plot.ruleX([0])
]
})
Insert cell
Insert cell
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
height: 600,
width,
marks: [
Plot.dot(
_.sampleSize(olympians, 5000),
Plot.dodgeX("middle", {
y: "height",
fill: "sex",
sort: "sex",
padding: -1,
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES
})
)
]
})
Insert cell
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
width,
marks: [
Plot.dot(
_.sampleSize(olympians, 2000),
Plot.dodgeX("middle", {
y: "height",
fx: "sex",
r: "weight",
fill: "sex",
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES
})
)
]
})
Insert cell
Insert cell
Plot.plot({

caption: "Heights of Olympic athletes",
width,
fx: {
domain: d3.groupSort(
olympians,
(g) => d3.median(g, (d) => d.height),
(d) => d.sport
),
tickRotate: 45
},
marginBottom: 100,
marks: [
Plot.frame(),
Plot.dot(
_.sampleSize(olympians, 3000),
Plot.dodgeX("middle", {
y: "height",
fx: "sport",
fy: "sex",
padding: -1,
fill: "sex",
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES
})
)
]
})
Insert cell
Insert cell
Plot.plot({
caption: "Heights of Olympic athletes",
width,
marginTop: 70,
fx: {
domain: d3.groupSort(
olympians,
(g) => d3.median(g, (d) => d.height),
(d) => d.sport
),
tickRotate: 45
},
marginBottom: 100,
marks: [
Plot.rectX(
olympians,
Plot.binY(
{ x: "count" },
{ y: "height", fill: "sex", fx: "sport", fy: "sex", tip: true }
)
)
]
})
Insert cell
Insert cell
Plot.plot({
caption: "Heights of Olympic athletes",
height: 800,
width,
x: {
domain: d3.groupSort(
olympians,
(g) => d3.median(g, (d) => d.height),
(d) => d.sport
),
tickRotate: 45
},
marginBottom: 100,
marks: [
Plot.boxY(olympians, {
x: "sport",
y: "height",
fy: "sex",
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES,
fill: "sex"
})
]
})
Insert cell
Insert cell
Plot.plot({
subcaption: "Heights of Olympic athletes",
height: 800,
width,
x: {
domain: d3.groupSort(
olympians,
(g) => d3.median(g, (d) => d.height),
(d) => d.sport
),
tickRotate: 45
},
marginBottom: 100,
marks: [
Plot.boxY(olympians, {
x: "sport",
y: "height",
fy: "sex",
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES,
fill: "sex"
}),
Plot.tickY(olympians, {
x: "sport",
y: "height",
fy: "sex",
tip: true,
channels: OLYMPIAN_TOOLTIP_ATTRIBUTES,
stroke: "sex",
strokeOpacity: 0.1
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
marks: [
Plot.rectY(walmarts, Plot.binX({ y: "count" }, { x: "date" })),
Plot.ruleY([0])
]
})
Insert cell
Insert cell
Plot.plot({
projection: "albers-usa",
fy: {
interval: "10 years",
tickFormat: (d) => `${d.getUTCFullYear()}’s`
},
marks: [
Plot.geo(statemesh, { strokeOpacity: 0.1 }),
Plot.geo(nation),
Plot.dot(walmarts, {
fy: "date",
x: "longitude",
y: "latitude",
fill: "currentColor"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
projection: "albers-usa",
color: {
label: "Age (years) →",
type: "linear",
domain: [0, 44],
reverse: true,
scheme: "Magma",
legend: true
},
marks: [
Plot.geo(statemesh, { strokeOpacity: 0.1 }),
Plot.geo(nation),
Plot.dot(walmarts, {
filter: (d) => d.date.getFullYear() <= year,
fill: (d) => year - d.date.getFullYear(),
stroke: "black",
strokeOpacity: 0.3,
strokeWidth: 1,
x: "longitude",
y: "latitude"
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
areaDots = Plot.plot({
r: { range: [0, radius] },
marks: [
Plot.dot(d3.range(1, 11), {
x: Plot.identity,
r: Plot.identity,
fill: "currentColor"
})
]
})
Insert cell
areaDots.scale("r")
Insert cell
Plot.lineX(
d3
.range(...areaDots.scale("r").domain)
.map((d) => areaDots.scale("r").apply(d) ** 2)
).plot({
x: { label: "r param" },
y: { label: "scaled r ** 2" }
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
grid: true,
color: {
legend: true,
type: "categorical",
domain: strokeSpecies ? ["Chinstrap", "Gentoo", "Adelie"] : undefined,
range: strokeSpecies
? ["rgb(197,92,199)", "rgb(0,116,112)", "rgb(255,128,36)"]
: undefined
},
marks: [
Plot.dot(penguins, {
x: "culmen_length_mm",
y: "culmen_depth_mm",
fill: strokeSpecies ? "species" : "N/A"
}),
Plot.linearRegressionY(penguins, {
x: "culmen_length_mm",
y: "culmen_depth_mm",
stroke: strokeSpecies ? "species" : undefined
})
]
})
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more