Public
Edited
Jul 3, 2023
Insert cell
Insert cell
Insert cell
overview = {
const parseDate = d3.timeParse("%d.%m.%Y");
return FileAttachment("overview.json")
.json()
.then((o) => {
return o.map((x, i) => ({
id: i,
...x,
datum: new Date(x.datum)
}));
});
}
Insert cell
domain_color_scale = d3.scaleOrdinal(d3.schemeCategory10)
Insert cell
domain_y_scale = d3
.scaleBand()
.domain(political_domains)
.range([32, height - 32])
Insert cell
import { addTooltip } from "@siliconjazz/basic-svg-tooltip"
Insert cell
political_domains = [...new Set(overview.map((x) => x.d1e1))].sort(
(a, b) => Number(a) - Number(b)
)
Insert cell
{
// Add tooltips
const svg = d3.select(overviewChart);
const circles = svg.selectAll("circle");
const tooltip = addTooltip(svg, circles);
const format = d3.utcFormat("%d.%m.%Y");

circles.on("mouseover", (e, d) => {
console.log(e, d);
tooltip.show(
`<b><small>${format(d.datum)}</small></b><br/>
${d.titel_kurz_f}<br/>${d.d1e1}`,
date_scale(d.datum),
domain_y_scale(d.d1e1)
);
});

circles.on("mouseleave", (e, d) => {
tooltip.hide();
});
}
Insert cell
cantonChart = {
const svg = d3.select(DOM.svg(width, height * 3.5));

const radiusScale = d3.scaleLinear([0, 70], [0, 10]);
const angleStep = (i) => {
return ((i * 0.05) / Math.sqrt(i)) * 30;
};

const cantons = Array.from(new Set(cantonsDf.map((d) => d.canton)));

const colNumber = 5;
const centers = Object.fromEntries(
cantons.map((c, i) => {
const row = Math.floor(i / colNumber);
const col = i % colNumber;
return [c, [row, col]];
})
);

const colScale = d3.scaleLinear([0, colNumber], [100, 1200]);
const rowScale = d3.scaleLinear([0, 5], [200, 1200]);

for (let canton of cantons) {
const g = svg
.append("g")
.attr(
"transform",
`translate(${colScale(centers[canton][1])}, ${rowScale(
centers[canton][0]
)})`
);

g.selectAll("circle")
.data(
cantonsDf.filter((d) => d.canton === canton),
(x) => x.id
)
.enter()
.append("circle")
.attr("cx", (d, i) => Math.cos(angleStep(i)) * radiusScale(i))
.attr("cy", (d, i) => Math.sin(angleStep(i)) * radiusScale(i))
.attr("fill", (x) => (x.ja > x.nein ? "green" : "red"))
.attr("fill-opacity", 0.5)
.attr("r", 2);

g.selectAll("text")
.data(overview, (x) => x.id)
.enter()
.append("text")
.text(canton)
.attr("x", -50)
.attr("font-family", "sans-serif")
.attr("y", -100);
}

return svg.node();
}
Insert cell
cantonsDf = {
return FileAttachment("cantons_df.json")
.json()
.then((data) =>
data.map((d, i) => ({
id: i,
...d
}))
);
}
Insert cell
Insert cell
width = 1100
Insert cell
height = 400
Insert cell
marginBottom = 20
Insert cell
marginLeft = 100
Insert cell
date_scale = d3.scaleTime(date_extent, [0 + 32, width - 32])
Insert cell
date_scale(new Date(1900, 1, 1))
Insert cell
date_extent = d3.extent(overview.map((x) => x.datum))
Insert cell
valid_votes_scale = d3.scaleLinear(
d3.extent(overview.map((d) => d.gultig)),
[3, 10]
)
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