Published
Edited
Nov 28, 2020
4 stars
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
svg.append("g")
.attr("transform", `translate(0,${height-20})`)
.attr("opacity", 0)
.call(d3.axisBottom(x))
.transition()
.delay(1800+1800/2)
.duration(1800/2)
.attr("opacity", 1);
const g = svg.append("g")
.attr("fill", "#B8BFC6")
.selectAll("rect")
.data(dataPos)
.join("rect")
.attr("x", d => d.x1)
.attr("y", d => d.y1)
.attr("width", squareSize)
.attr("height", squareSize)
.attr("fill", d => color(d.party))
.attr("stroke-width", 0.5)
.attr("stroke", "white")
if (play) {
g.transition()
.delay(100)
.duration(1800)
.attr("fill", d => d3.interpolateBlues(1 - d.ministryIndex / sortedMinistries.length))
.transition()
.delay(100)
.duration(1800)
.attr("x", d => x(d.bins.x0))
.attr("y", d => height - 30 - d.bins.pos * squareSize)
}

return svg.node();
}
Insert cell
dataPos = {
const nMinistries = new Map();
sortedData.forEach((d, i) => {
d.x0 = i * barWidth;
d.count = 0;
if (nMinistries.has(d.ministryIndex)) {
d.count = nMinistries.get(d.ministryIndex) + 1;
nMinistries.set(d.ministryIndex, d.count);
} else {
nMinistries.set(d.ministryIndex, 0);
}
d.col = Math.floor(d.count / nRows);
d.row = nRows - (d.count % nRows);
d.x1 = d.col * squareSize;
d.y1 = d.ministryIndex * (nRows * squareSize + squareSize / 2) + d.row * squareSize;
})
return sortedData;
}
Insert cell
bins = rawBins.map(({x0, x1, elements}) => {
const sortedElements = Object.values(elements).sort((a, b) => d3.ascending(a.ministryIndex, b.ministryIndex));
sortedElements.map(d => {
d.bins = {x0, x1, pos: sortedElements.findIndex(e => e === d)};
return d;
});
return {x0, x1, elements};
})
Insert cell
rawBins = hist(data).map(({x0, x1, ...rest}) => ({x0, x1, elements: Object.values(rest).sort((a, b) => d3.ascending(a.ministryIndex, b.ministryIndex))}))
Insert cell
hist = d3.histogram()
.value(d => d.publishedAt)
.domain(x.domain())
.thresholds(thresholds)
Insert cell
x = d3.scaleTime()
.domain(corrTimeExtent)
.range([0, width])
Insert cell
thresholds = d3.timeMonths(corrTimeExtent[0], corrTimeExtent[1]);
Insert cell
corrTimeExtent = [
d3.timeMonth.offset(timeExtent[0], -1),
d3.timeMonth.offset(timeExtent[1], 1)
]
Insert cell
timeExtent = d3.extent(data, d => d.publishedAt)
Insert cell
sortedData = data.sort((a, b) => d3.ascending(a.partyIndex, b.partyIndex) || d3.ascending(a.party, b.party) || d3.ascending(a.publishedAt, b.publishedAt))
Insert cell
data = rawData.map(d => {
d.ministryIndex = sortedMinistries.findIndex(m => m === d.ministry);
d.partyIndex = sortedParties.findIndex(m => m === d.party);
return d;
})
Insert cell
sortedParties = d3.rollups(parties, v => v.length, d => d).sort((a, b) => d3.descending(a[1], b[1])).map(d => d[0])
Insert cell
uniqueParties = new Set(parties)
Insert cell
parties = rawData.map(d => d.party)
Insert cell
sortedMinistries = Array.from(ministriesCount).sort((a, b) => d3.descending(a[1], b[1])).map(d => d[0])
Insert cell
ministriesCount = d3.rollup(ministries, v => v.length, d => d)
Insert cell
uniqueMinistries = new Set(ministries)
Insert cell
ministries = rawData.map(d => d.ministry)
Insert cell
rawData = {
const parseTime = d3.timeParse("%Y-%m-%d");
return d3.csvParse(await FileAttachment("bawu_test@6.csv").text(), d => ({
publishedAt: parseTime(d.published_at),
party: d.party,
ministry: d.ministry,
}))
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import {button} from "@jashkenas/inputs"
Insert cell
d3 = require('d3@6')
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