Public
Edited
Jan 10, 2023
5 forks
Insert cell
Insert cell
Insert cell
Insert cell
viewof passengerClass = Inputs.select(
new Map([
["All classes", null],
["1st class", 1],
["2nd class", 2],
["3rd class", 3]
]),
{ label: "Passenger Class" }
)
Insert cell
**Selected Gender:** ${(selectedSex === null) ? 'None' : selectedSex}

**Selected Survived:** ${(selectedSurvived === null) ? 'None' : selectedSurvived}
Insert cell
Insert cell
Plot.plot({
marks: [Plot.rectY(filteredData, Plot.binX({ y: "sum" }, { x: "age" }))]
})
Insert cell
Insert cell
Plot.plot({
marks: [Plot.rectY(filteredData, Plot.binX({ y: "sum" }, { x: "fare" }))]
})
Insert cell
Insert cell
survivedPieChart = PieChart(
survivedPieData,
d3.schemeSet3.slice(2),
function (d) {
if (selectedSurvived === d.data.key) {
mutable selectedSurvived = null;
} else {
mutable selectedSurvived = d.data.key;
}
}
)
Insert cell
Insert cell
sexPieChart = PieChart(sexPieData, d3.schemeSet3, function (d) {
if (selectedSex === d.data.key) {
mutable selectedSex = null;
} else {
mutable selectedSex = d.data.key;
}
})
Insert cell
Insert cell
function PieChart(data, colorScheme, onClick) {
const margin = 10;
const radius = 100;

// Creates sources <svg> element
const svg = d3
.create("svg")
.attr("width", radius * 2 + margin * 2)
.attr("height", radius * 2 + margin * 2);

// Group used to enforce margin
const g = svg
.append("g")
.attr("transform", `translate(${radius + margin},${radius + margin})`);

const pie = d3
.pie()
.value((d) => d.values.length)
.sortValues(null)
.sort(null);

const pied = pie(data); // {key: string, values: IPerson[]}[]

const arc = d3.arc().outerRadius(radius).innerRadius(0);

const cscale = d3.scaleOrdinal(colorScheme).domain(data.map((d) => d.key));

// DATA JOIN
const path = g
.selectAll("path")
.data(pied, (d) => d.data.key)
.join(
// ENTER
// new elements
(enter) => {
const path_enter = enter.append("path");
// TODO register click handler to change selected sex in state and call updateApp()
path_enter.append("title");
path_enter.on("click", (event, d) => {
onClick(d);
});
return path_enter;
}
);

// ENTER + UPDATE
// both old and new elements
path
.classed("selected", (d) => d.data.key === svg.value)
.attr("d", arc) // TODO set the CSS class `selected` if the current data item is the selected sex in the state
.style("fill", (d) => cscale(d.data.key));

path.select("title").text((d) => `${d.data.key}: ${d.data.values.length}`);

return svg.node();
}
Insert cell
Insert cell
data = FileAttachment("titanic3.csv").csv({ typed: true })
Insert cell
filteredData = data.filter((d) => {
if (passengerClass && d.pclass !== passengerClass) {
return false;
}
if (selectedSex !== null && d.sex !== selectedSex) {
return false;
}
if (selectedSurvived !== null && d.survived !== selectedSurvived) {
return false;
}
return true;
})
Insert cell
mutable selectedSurvived = null
Insert cell
survivedPieData = [0, 1].map((key) => ({
key,
values: filteredData.filter((d) => d.survived === key)
}))
Insert cell
mutable selectedSex = null
Insert cell
sexPieData = ["male", "female"].map((key) => ({
key,
values: filteredData.filter((d) => d.sex === key)
}))
Insert cell
Insert cell
We're almost done for the basic dashboard, the only thing left is the fullscreen option. This is very important for a dashboard because multiple views can be difficult to see at the same time (especially in Observable). Import the fullscreen option from this notebook by [@pierreleripoll in his notebook](https://observablehq.com/@pierreleripoll/vegasync) and specify how you would like the fullscreen to behave.
Insert cell
import { fullscreen } from "@pierreleripoll/vegasync"
Insert cell
<style>
rect {
fill: steelblue;
fill-opacity: 0.8;
}

rect:hover {
fill-opacity: 1;
}

path {
fill-opacity: 0.8;
}

.selected,
path:hover {
fill-opacity: 1;
}

.axis {
font-size: smaller;
}
</style>
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