Published
Edited
Feb 8, 2022
6 forks
Importers
39 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Plot.plot({
// Configure the x scale
x: {
type: "log", // set the type
axis: "top" // place the axis on top of the chart
},
// Display dots for 100 random numbers
marks: [
Plot.dotX(
d3.range(100).map((d) => Math.random() * 100 + 1),
{ strokeWidth: 0.5, fill: "blue" }
)
],
height: 50,
marginBottom: 10
})
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
Insert cell
import {
createDemo,
intro,
plotWidth,
welcomeBox,
download,
inputStyles,
deck
} from "@observablehq/cheatsheet-utilities"
Insert cell
import {toc} from "@nebrius/indented-toc"
Insert cell
import {textcolor} from "@observablehq/text-color-annotations-in-markdown"
Insert cell
Insert cell
// Create a list of examples
continuousExamples = ["linear", "log", "symlog", "pow", "sqrt", "identity"]
.sort()
.map((type) => {
const header = {
type: "text",
value: `// ${continuousComments.get(type)}\nPlot.plot({x: {`
};
const typeControl = { param: "type", value: type };
const closer = { type: "text", value: "}})" };
const extraControl =
type === "log"
? {
param: "extra",
label: "base",
type: "radio",
options: [2, 10],
value: 10
}
: type === "pow"
? {
param: "extra",
label: "exponent",
type: "range",
min: 0,
max: 10,
step: 0.5,
value: 2
}
: type === "symlog"
? {
param: "extra",
label: "constant",
type: "range",
min: 0,
max: 1000,
step: 5,
value: 5
}
: null;

const extraDetail = (value) =>
type === "log"
? `,\n\t\tbase: ${value}`
: type === "pow"
? `,\n\t\texponent: ${value}`
: type === "symlog"
? `,\n\t\tconstant :${value}`
: "";
const domain = type === "log" ? "[100, 1000]" : "[-1000, 1000]";
const controls = [header, typeControl, extraControl, closer].filter(
(d) => d !== null
);
return {
controls,
plot: (config) => `Plot.plot({
x: {
domain: ${domain},
type: "${type}",
grid: true${extraDetail(config.extra)}
},
height: 50,
width: ${plotWidth}
})`
};
})
Insert cell
categoricalExamples = ["point", "band"].map((type) => ({
controls: [
{
type: "text",
value: `// ${
type === "point" ? "Point scale" : "Band scale"
}\nPlot.plot({x: {`
},
{
param: "type",
value: type
},
{
param: "padding",
type: "range",
min: 0,
max: 1,
value: 0.1,
step: 0.1
},
{
param: "align",
type: "range",
min: 0,
max: 1,
value: 0.5,
step: 0.1
},
{
type: "text",
value: `})`
}
],
plot: (config) => {
return `Plot.plot({
x: {
padding: ${+config.padding},
align: ${+config.align},
type: "${type}",
domain: [..."ABCDEFGHIJ"]
},${
type === "point"
? ``
: `\n\tmarks: [
Plot.cell([..."ABCDEFGHIJ"], {
x: (d) => d,
fill: "none",
stroke: "currentColor"
})
],`
}
grid: true,
width: ${plotWidth}
})`;
}
}))
Insert cell
customDateConfig = ({
controls: [
{
type: "text",
value: `// Custom date format`
},
{
type: "text",
value: `Plot.plot({x:{`
},
{
param: "time",
label: `tickFormat`,
type: "textInput",
value: "%A %B %d, %Y"
},
{
type: "text",
value: `}})`
},
],
plot: (config) => `Plot.plot({
x: {
tickFormat: d3.utcFormat("${config.time}"),
domain: [d3.utcYear.offset(d3.utcYear(), -2), d3.utcYear()],
ticks: 3,
nice: true
},
marginLeft: 100,
marginRight: 100,
width: ${plotWidth}
})`
})
Insert cell
oneNumberConfig = ({
controls: [
{
type: "text",
value: `// Tick formatting:`
},
{
param: "symbol",
type: "select",
options: ["", "$", "#"],
value: ""
},
{
param: "comma",
type: "toggle",
value: true
},
{
param: "precision",
type: "range",
min: 0,
max: 10,
value: 1,
step: 1
},
{
param: "type",
type: "select",
options: typeOptions,
value: "f"
},
{type: "text", value: "// data options"},
{
param: "domain",
type: "textInput",
value: "[1, 10000]"
},
{
param: "log",
type: "toggle",
value: false
},
],
plot: (config) => `Plot.plot({
x: {
tickFormat: d3.format("${config.symbol}${config.comma ? "," : ""}.${config.precision}${config.type}"),
domain: ${config.domain},
type: "${config.log ? "log" : "linear"}",
ticks: 5,
line: true,
nice: true
},
width: ${plotWidth},
marginRight: 50,
marginLeft: 50
})`
})
Insert cell
dateExamples =({
controls: [
{
type: "text",
value: `// Date scales\nPlot.plot({x: {`
},
{ param: "type", type: "radio", options: ["utc", "time"], value: "utc"},
{
type: "text",
value: `}})`
},
],
plot: (config) =>
`Plot.plot({
x: { type: "${config.type}", domain: [1614556800000, 1614637527840.0002] },
grid: true,
width: ${plotWidth}
})
`,
})
Insert cell
tickDemo = ({
controls: [
{ type: "text", value: "// Format ticks\nPlot.plot({x: " },
...optionsExamples.filter((d) => d.group === "tick"),
{ type: "text", value: "}})" }
],
plot: (config) => `Plot.plot({
marks: [
Plot.dot(
[{ value: 0.1 }, { value: 0.25 }, { value: 0.3 }, { value: 0.42 }],
{ x: "value" }
)
],
x: {
tickRotate: ${config.tickRotate},
ticks: ${config.ticks},
tickSize: ${config.tickSize},
line: ${config.line},
tickPadding: ${config.tickPadding},
labelAnchor: "${config.labelAnchor}",
labelOffset: ${config.labelOffset},
nice: ${config.nice},
label: "${config.label}"
},
height: 200,
width: ${plotWidth},
marginBottom: 100
})`
})
Insert cell
dateConfig = Object.entries({
Year: ["%Y", "%y"],
Month: ["%b", "%B", "%m"],
Day: ["%a", "%A", "%d", "%e"],
Hour: ["%H:%M", "%I%p"]
}).map(([time, options]) => ({
controls: [
{
type: "text",
value: `// ${time} formatting:`
},
{
type: "text",
value: `Plot.plot({x:{`
},

{
param: "time",
label: `tickFormat`,
type: "select",
options: options,
value: options[0]
},
{
type: "text",
value: `}})`
}
],
plot: (config) => `Plot.plot({
x: {
tickFormat: d3.utcFormat("${config.time}"),
domain: [d3.utc${time}.offset(d3.utc${time}(), -${
time === "Day" ? 7 : 12
}), d3.utc${time}()]
},
width: ${plotWidth}
})`
}))
Insert cell
axisDemo = ({
controls: [
{ type: "text", value: "// Customize axis\nPlot.plot({x:" },
...optionsExamples.filter((d) => d.group !== "tick"),
{ type: "text", value: "}})" }
],
plot: (config) => `Plot.plot({
marks: [
Plot.dot(
[{ value: 0.1 }, { value: 0.25 }, { value: 0.3 }, { value: 0.42 }],
{ x: "value" }
)
],
x: {
axis: "${config.axis}",
grid: ${config.grid},
percent: ${config.percent},
reverse: ${config.reverse},
zero: ${config.zero},
inset: ${config.inset},
domain: ${config.domain}
},
width: ${plotWidth}
})`
})
Insert cell
// Set of examples to create
optionsExamples = [
{
param: "tickRotate",
value: -45,
type: "range",
min: -90,
max: 90,
group: "tick",
step: 1
},
{
param: "ticks",
value: 5,
type: "range",
min: 0,
max: 15,
step: 1,
group: "tick"
},
{ param: "axis", value: "top", type: "select", options: ["top", "bottom"] },
{
param: "tickSize",
type: "range",
step: 1,
min: 0,
max: 15,
group: "tick",
value: 5
},
{ param: "line", value: true, type: "toggle", group: "tick" },
{
param: "tickPadding",
value: 10,
type: "range",
step: 1,
min: 0,
max: 15,
group: "tick"
},

{
param: "labelAnchor",
type: "select",
options: ["left", "center", "right"],
value: "left",
group: "tick"
},
{
param: "labelOffset",
value: 0,
min: -20,
max: 20,
type: "range",
step: 1,
group: "tick"
},
{ param: "grid", value: true, type: "toggle" },
{ param: "percent", value: true, type: "toggle" },
{ param: "reverse", value: true, type: "toggle" },
{ param: "zero", value: false, type: "toggle" },
{ param: "nice", value: true, type: "toggle", group: "tick" },

{ param: "inset", value: 75, type: "range", min: 0, max: 99, step: 1 },

{ param: "label", type: "textInput", value: "My label", group: "tick" },
{ param: "domain", type: "textInput", value: `[1, 30]` }
]
Insert cell
customConfig = ({
controls: [
{
type: "text",
value: `// Custom formatting:`
},
{
type: "text",
value: `Plot.plot({x:{`
},

{
param: "tickFormat",
label: `tickFormat`,
type: "select",
options: new Map([
["d => d", (d) => d],
["d => d.slice(0,3)", (d) => d.slice(0, 3)],
[
"d => 'My group is: ' + d.match(/[0-9]/)[0]",
(d) => "My group is: " + d.match(/[0-9]/)[0]
],
["d => d.split(' ')[1]", (d) => d.split(" ")[1]],
["d => d.toUpperCase()", (d) => d.toUpperCase()],
["null", null]
]),
value: (d) => d.slice(0, 3)
},
{
type: "text",
value: `}})`
}
],
plot: (config) => `Plot.plot({
x: {
tickFormat: ${config.tickFormat},
domain: ["group 1", "group 2", "group 3"],
ticks: 3,
nice: true
},
marginLeft: 100,
marginRight: 100,
width: ${plotWidth}
})`
})
Insert cell
typeOptions = new Map(
[
{ value: "e", label: "exponent notation." },
{ value: "f", label: "fixed point notation." },
{
value: "g",
label:
"either decimal or exponent notation, rounded to significant digits."
},
{ value: "r", label: "decimal notation, rounded to significant digits." },
{
value: "s",
label:
"decimal notation with an SI prefix, rounded to significant digits."
},
{
value: "%",
label: "multiply by 100, and then decimal notation with a percent sign."
},
{
value: "p",
label:
"multiply by 100, round to significant digits, and then decimal notation with a percent sign."
},
{ value: "b", label: "binary notation, rounded to integer." },
{ value: "o", label: "octal notation, rounded to integer." },
{ value: "d", label: "decimal notation, rounded to integer." },
{
value: "x",
label:
"hexadecimal notation, using lower-case letters, rounded to integer."
},
{
value: "X",
label:
"hexadecimal notation, using upper-case letters, rounded to integer."
},
{ value: "c", label: "character data, for a string of text." }
].map((d) => [`${d.value} (${d.label})`, d.value])
)
Insert cell
continuousComments = new Map([
["identity", "No transformation"],
["linear", "Linear scale"],
["log", "Log scale"],
["pow", "Exponential scale"],
["sqrt", "Square root scale"],
["symlog", "Symetric log scale"]
])
Insert cell
formats = [
{
syntax: "s",
properties: ["type"],
description: "International System of Units (SI)."
},
{
syntax: ".2s",
properties: ["precision", "type"],
description: "Two significant digits, shown in SI."
},
{ syntax: ",", properties: ["comma"], description: "Comma separated" },
{
syntax: ",.1f",
properties: ["comma", "precision", "type"],
description: "Comma separated, one fixed value after the decimal place"
},
{
syntax: ",.1p",
properties: ["comma", "precision", "type"],
description: "Comma separated, one digit, percentage type"
},
{
syntax: "$,.1",
properties: ["symbol", "comma", "precision", "type"],
description: "Currency syntax, Comma separated, one digit, percentage type"
}
]
Insert cell
Insert cell
color = d3
.scaleOrdinal()
.domain(["symbol", "comma", "precision", "type"])
.range(d3.schemeTableau10)
Insert cell
tv = (value, text) => textcolor(value, { color: color(text), padding: "0" })
Insert cell
tc = (text) => textcolor(text, { color: color(text), padding: "0" })
Insert cell
introParagraph = () => htl.html`<p style="margin-top:0px"><a href ="https://observablehq.com/@observablehq/plot?collection=@observablehq/plot" target="_blank">Observable Plot</a> uses <a href="https://observablehq.com/@observablehq/plot-scales?collection=@observablehq/plot" target="_blank">scales</a> to map abstract values in your data, such as time or temperature, to visual values in plot, such as x- or y- position, or color. The scale’s type, as well as the visual marks that accompany it (such as axes, ticks, and labels) can be configured in the <code>Plot.plot()</code> function.`
Insert cell
smallNumber = .00013
Insert cell
largeNumber = 543005
Insert cell
Insert cell
<style>
.demo-wrapper {
margin-top:8px !important;
}
input, canvas, button {
vertical-align: bottom; /* unsure why this is needed to keep the radio buttons aligned */
}
</style>
Insert cell
inputStyles
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more