Public
Edited
Jun 6, 2023
Insert cell
Insert cell
Insert cell
Insert cell
data = FileAttachment("palmer-penguins.csv").csv({typed: true})
Insert cell
Insert cell
Insert cell
Insert cell
Inputs.table(data)
Insert cell
Insert cell
Insert cell
Plot // Plot is available in Observable by default
Insert cell
Insert cell
Insert cell
Insert cell
viewof x = Inputs.select(data.columns)
Insert cell
// change the code to replace … by the field’s name, e.g. body_mass
Plot.dot(data,
{x: x, fill: "black", fillOpacity: 0.2}
).plot()
Insert cell
Insert cell
Insert cell
// change the code to replace … by the field’s name, e.g. body_mass
Plot.dot(data,
{x: "body_mass", y: "flipper_length"}
).plot()
Insert cell
Insert cell
Insert cell
// type your code here
Plot.dot(data,
{x: "body_mass", y: "flipper_length", fill: "species"}
).plot()

Insert cell
Insert cell
Plot.dot(data,
{x: "flipper_length", y: "body_mass", fill: "species", title: "species"})
.plot(
{
grid: true ,
color: {
domain: ["Adelie", "Gentoo", "Chinstrap"].reverse(),
//range: ["red", "green", "blue"]
scheme: "dark2"
}
}
)
Insert cell
Insert cell
// type your code here
Plot.dot(
chart_data,
{x: "flipper_length", y: "body_mass", fill: "species"}
).plot({
width,
facet:{
data: chart_data,
x: "sex",
y: "island",
marginLeft: 10,
marginRight: 100
},
marks:[Plot.frame()]
})

Insert cell
chart_data = data.filter(d => !!d.sex) // filter na missing
Insert cell
Insert cell
Insert cell
// type your code here
Plot.barX(
data,
Plot.groupY({x: "count"},
{y: "species"})
).plot()

Insert cell
// type your code here
Plot.barX(
data,
Plot.groupY(
{x: "mean"}, // calculation - what is the output
{y: "species", x:"flipper_length"} // what I'm picking from the data
)
).plot({
marginLeft:100,
y:{label:""}
})
Insert cell
Plot.barX(
data,
Plot.groupY(
{x: "mean"}, // calculation - what is the output
{y: "species", x:"flipper_length"} // what I'm picking from the data
)
).plot({
marginLeft:100,
y:{
label:"",
domain: speciesList
}
})
Insert cell
import {tidy, mean, arrange, desc, groupBy, summarize} from "@pbeshai/tidyjs"
Insert cell
speciesList = tidy(
data,
groupBy("species",
summarize({mean_length: mean("flipper_length")})),
arrange(desc("mean_length"))
).map(d => d.species)
Insert cell
Insert cell
Insert cell
// type your code here
Plot.plot({
facet: {
data,
x: "sex"
},
marks: [
Plot.barY(data, Plot.groupX(
{y: "count"},
{x: "species", fy: "island", fill: "sex", fx: "sex"}
))
],

marginRight: 100
})

Insert cell
Insert cell
Insert cell
data
Insert cell
// type your code here
Plot.plot({
marks:[
Plot.rectY(data, Plot.binX({y2: "count"}, {x: "body_mass", fill: "sex", mixBlendMode: "screen"})),
Plot.ruleY([0]),
Plot.ruleX([0])
]
})

Insert cell
Plot.binX({y: "count"}, {x: "body_mass", fill: "sex"})
Insert cell
Plot.plot({
grid: true,
color: {scheme: "Purples"},
marks: [
Plot.rectX(data, Plot.bin({fill: "count"}, {x: "body_mass", y: "flipper_length", thresholds: 30}))
]
})
Insert cell
Plot.plot({
r: {range: [0, 6]},
grid: true,
marks: [
Plot.dot(data, Plot.bin({r: "count"}, {x: "body_mass", y: "flipper_length", stroke: "sex", fill: "sex"}))
]
})
Insert cell
Plot.plot({
marginLeft: 100,
padding: 0,
x: {grid: true},
color: {scheme: "Blues"},
marks: [
Plot.rect(data, Plot.binX({fill: "proportion-facet"}, {x: "body_mass", fy: "island", inset: 0.5}))
]
})
Insert cell
Insert cell
Insert cell
// type your code here
Plot.rectY(data,
Plot.binX({y: "count"},
{x: "body_mass",
thresholds: 20,
fy: "sex", fx: "species"}))
.plot()

Insert cell
Plot.rectY(data, Plot.binX({y: "count"}, {x: "body_mass", thresholds: 20, fill: "species"}))
.plot()
Insert cell
Insert cell
Insert cell
Plot.plot({
facet: {
data,
x: "species",
y: "sex"
},
marks: [
Plot.frame(),
Plot.rectY(data, Plot.binX({y: "count"}, {x: "body_mass", fill: "species", thresholds: 30})),
Plot.tickX(data, Plot.groupZ({x: "median"}, {x: "body_mass", stroke: "black"}))
]
})

Insert cell
Insert cell
Insert cell
function selectorMedian(I, V) {
const median = d3.median(I, (i) => V[i]);
const i = d3.least(I, (i) => Math.abs(V[i] - median));
return [i];
}
Insert cell
// type your code here
Plot.plot({
height: 100,
marks: [
Plot.dotX(data, Plot.dodgeY({filter: d => d.sex === "FEMALE", x: "body_mass"})),
Plot.tickX(data, Plot.select({x: "min"}, ({filter: d => d.sex === "MALE", x: "body_mass", stroke: "red"}))),
Plot.tickX(data, Plot.select({x: selectorMedian}, {filter: d => d.sex === "FEMALE", x: "body_mass", stroke: "green"}))
]
})

Insert cell
Insert cell
Insert cell
// type your question here
Plot.plot({
marks: [Plot.rectY({data,
Plot.binX({y:"count"}, {x:"species"})})]
})

Insert cell
// type your code here


Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function answer({
title,
questions = [],
guides = [],
hints = [],
solutions = [],
open = !!showAll
}) {

const div = d3.create("div").classed("answer", true);

if (title) {
div.append("hr");
div.append("h2").html(title);
}

div.call(renderGroup, questions, "question", true, d => md`${d}`);
// div.call(renderGroup, guides, "guide", open, d => md`${d}`);
div.call(renderGuide, guides, "guide", open, d => md`${d}`);
div.call(renderGroup, hints, "hint", open, d => code(d, "hint"));
div.call(renderGroup, solutions, "solution", open, d => code(d, "solution", renderSnippet));

return div.node();
}
Insert cell
function Q(q) {
return Object.assign(answer({
...q,
guides: null,
hints: null,
solutions: null
}), {value: q})
}
Insert cell
function A(q) {
return answer({
...q,
title: null,
questions: null
})
}
Insert cell
function renderGroup(div, group, type, open, render) {
if (group?.length) {
const details = div.append(type==="question" ? "div" : "details");
if (open) details.attr("open", "open")
if (type !== "question") details.append("summary").append("strong").text(`${type}${group.length > 1 ? "s" : ""}`);
details.append("ul").selectAll().data(group).join("li").append(render);
}
}
Insert cell
function renderGuide(div, group, type, open, render) {
if (group?.length) {
const details = div.append("div");
if (open) details.attr("open", "open")
// details.append("span").append("strong").text(`${type}${group.length > 1 ? "s" : ""}`);
details.append("ul").selectAll().data(group).join("li").append(render);
}
}
Insert cell
function renderSnippet(str) {
try {
const func = new Function("data", "Plot", "d3", "width", `return ${str}`)
return func(data, Plot, d3, width);
}
catch(e) {}
}
Insert cell
function code(code, type, visual) {
return html`
<div class="copy">${Copier("Copy", {value: code})}</div>
<textarea class=${type} rows=${rows(code)}>${code}</textarea>
${visual ? visual(code) : ""}`;

}
Insert cell
function rows(code) {
const lines = code.trim().split("\n").length;
return Math.max(Math.min(lines, 15), 2);
}
Insert cell
styles = html`<style>
.answer {
font-family: system-ui, sans-serif;
font-size: 14px;
}
.answer summary strong {
text-transform: capitalize;
}
.answer li {
list-style: none;
position: relative;
}
.answer textarea {
font: var(--monospace-font);
font-size: 12px;
width: 100%;
padding: 5px;
border: 2px solid #3b5fc0;
background: #F6F9FF;
border-radius: 5px;
margin-bottom: 2em;
resize: none;
}
.answer .copy form {
position: absolute;
right: -4px;
top: 4px;
width: initial;
}
.answer summary {
display: inline-block;
padding: 2px 6px;
border: 2px solid #3b5fc0;
background: #F6F9FF;
border-radius: 5px;
margin: 2px 0;
outline-offset: -2px;
list-style: none;
cursor: pointer;
min-width: 62px;
text-align: center;
}

.answer details[open] > summary {
background: #3b5fc0;
color: white;
}

`
Insert cell
html = htl.html
Insert cell
import {Copier} from "@mbostock/pbcopy"
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