Public
Edited
Oct 24, 2024
Paused
2 stars
Insert cell
Insert cell
Insert cell
{
const width = 840;
const height = 150;

// The size of the point mark is calculated as the area
// of a square, s², for consistency with the square shape if used
const s = 7;
const sizeSq = s ** 2;

const tickSizeY = 5;
const gridClr = "#e2e2e2";

const hover = {
name: "hover",
select: { type: "point", on: "mouseover", clear: "mouseout" },
views: ["dotLayer"]
};

const dots = {
name: "dotLayer",
mark: { type: "point" },
data: {
values: laureates
},
encoding: {
x: {
field: "awardYear",
type: "temporal",
scale: { domainMin: { year: 1900 } },
title: "Award year →"
},
y: {
field: "genderOffset",
type: "quantitative",
stack: true,
axis: { values: [5, 0, -5, -10] },
title: "← Men · Women →"
},
color: {
field: "gender",
scale: {
domain: ["male", "female"],
range: ["#bfb498", "#dc5a74"]
},
legend: null
},
stroke: {
condition: { value: "#000", param: "hover", empty: false },
value: "#fff"
},
size: {
condition: {
value: sizeSq * 1.2,
param: "hover",
empty: false
},
value: sizeSq
},
order: { condition: { param: "hover", value: 1 }, value: 0 },
tooltip: [
{ field: "name", title: "Name" },
{ field: "category", title: "Category" },
{
field: "awardYear",
title: "Award year",
timeUnit: "year"
}
]
}
};

const rule = {
mark: {
type: "rule",
x: -tickSizeY,
x2: width + tickSizeY
},
data: {
values: [
"We just need an array of length 1 to draw the rule mark once. You can use a string (as in this example), a number, or just an empty object {}."
]
},
encoding: {
y: { datum: 0 }
}
};

const config = {
view: { stroke: null },
font: franklinLight,
title: { fontSize: 25, font: bodoni, offset: 10 },
point: {
filled: true,
strokeWidth: 1,
cursor: "pointer"
},
rule: {
strokeWidth: 0.8
},
axis: {
domain: false,
labelColor: "#808080",
labelFontSize: 14,
labelPadding: 5,
titleFontSize: 15,
titleFontWeight: 400,
titlePadding: 15
},
axisX: {
grid: false,
offset: 10,
tickCount: 10,
tickSize: 2 * tickSizeY,
labelFlush: false,
titleAnchor: "end"
},
axisY: {
labelExpr: "abs(datum.value)",
tickSize: tickSizeY,
gridColor: gridClr,
tickColor: gridClr,
titleY: 0.2 * height
}
};

return render({
width: width,
height: height,
title: "Nobel Prize Laureates",
params: [hover],
layer: [dots, rule], // Marks
config: config
});
}
Insert cell
Insert cell
Insert cell
Insert cell
laureates
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
laureates = {
const data = await d3.json(
"https://api.nobelprize.org/2.1/laureates?limit=10000"
);
return (
aq
.from(data.laureates)
// Filter out organizations
.filter((d) => d.knownName !== undefined)
.unroll("nobelPrizes")
.derive({
awardYear: aq.escape((d) => d.nobelPrizes.awardYear),
category: aq.escape((d) => d.nobelPrizes.category.en),
name: aq.escape((d) => d.knownName.en),
genderOffset: (d) => (d.gender === "female" ? 1 : -1)
})
.select("name", "gender", "awardYear", "category", "genderOffset")
// .view()
.objects()
);

// Without Arquero
// return data.laureates
// .filter((d) => d.knownName !== undefined)
// .flatMap((d) =>
// d.nobelPrizes.map((prize) => ({
// name: d.knownName.en,
// gender: d.gender,
// awardYear: prize.awardYear,
// category: prize.category.en
// }))
// );
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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