Published
Edited
May 14, 2020
7 stars
Insert cell
Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height))
.attr("viewBox", `${-width / 2} ${-height / 2} ${width} ${height}`)
.style("width", "100%")
.style("height", "auto")
.style("font", "10px sans-serif");

svg.append("g")
.selectAll("g")
.data(d3.stack().keys(data.columns.slice(startCol,data.columns.length-endColDiff))(data))
.enter().append("g")
.attr("fill", d => z(d.key))
.selectAll("path")
.data(d => d)
.enter().append("path")
.attr("d", arc);

svg.append("g")
.call(xAxis);

svg.append("g")
.call(yAxis);

svg.append("g")
.call(legend);

return svg.node();
}
Insert cell
data = d3.text("https://raw.githubusercontent.com"
+ "/monicagg/learn-practice/master"
+ "/d3js/uk-raindays/UK_raindays.txt").then(function(text) {
let rows = d3.dsvFormat("\n").parseRows(text);
let data = [], i=0;
data.columns = [];
rows.forEach( row => {
//console.log("row - " + typeof row[0] + " " + row[0]);
const year = row[0].slice(0,4);
const elems = row[0].split(' ');
if (year.startsWith("year")) {
elems.forEach( elem => {
if (elem.trim().length>0) {
data.columns.push(elem.valueOf());
}
});
//console.log("data.columns - " + data.columns);
}
if (!Number.isNaN(Number.parseInt(year))) {
let j=0;
let strElem = "data[" + i + "] = { ";
elems.forEach( elem => {
if (elem.trim().length>0) {
strElem = strElem.concat(JSON.stringify(data.columns[j]) + ": \"" + elem + "\",");
j++;
}
});
strElem = strElem.concat(" }");
//console.log("strElem - " + strElem);
eval(strElem);
i++;
}
});
return data;
});
Insert cell
arc = d3.arc()
.innerRadius(d => y(d[0]))
.outerRadius(d => y(d[1]))
.startAngle(d => x(d.data.year))
.endAngle(d => x(d.data.year) + x.bandwidth())
.padAngle(0.01)
.padRadius(innerRadius)
Insert cell
x = d3.scaleBand()
.domain(data.map(d => d.year))
.range([0, 2 * Math.PI])
.align(0)
Insert cell
y = {
// This scale maintains area proportionality of radial bars!
const y = d3.scaleLinear()
.domain([0, d3.max(data, d => +d.ann)])
.range([innerRadius * innerRadius, outerRadius * outerRadius]);
return Object.assign(d => Math.sqrt(y(d)), y);
}
Insert cell
z = d3.scaleOrdinal()
.domain(data.columns.slice(startCol,data.columns.length-endColDiff))
.range(["#98abc5", "#DAF7A6", "#239b56", "#FF8C00", "#FFA500", "#FFD700", "#808000", "#d0743c", "#a05d56", "#7b6888", "#8a89a6", "#1e8449"])
Insert cell
xAxis = g => g
.attr("text-anchor", "middle")
.call(g => g.selectAll("g")
.data(data)
.enter().append("g")
.attr("transform", d => `
rotate(${((x(d.year) + x.bandwidth() / 2) * 180 / Math.PI - 90)})
translate(${innerRadius},0)
`)
.call(g => g.append("line")
.attr("x2", -5)
.attr("stroke", "#000"))
.call(g => g.append("text")
.attr("transform", d => (x(d.year) + x.bandwidth() / 2 + Math.PI / 2) % (2 * Math.PI) < Math.PI
? "rotate(0)translate(-18,5)"
: "rotate(-180)translate(18,5)")
.text(d => d.year)))
Insert cell
yAxis = g => g
.attr("text-anchor", "middle")
.call(g => g.append("text")
.attr("y", d => -y(y.ticks(5).pop()))
.attr("dy", "-1em")
.text("Rain days"))
.call(g => g.selectAll("g")
.data(y.ticks(5).slice(1))
.enter().append("g")
.attr("fill", "none")
.call(g => g.append("circle")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.5)
.attr("r", y))
.call(g => g.append("text")
.attr("y", d => -y(d))
.attr("dy", "0.35em")
.attr("stroke", "#fff")
.attr("stroke-width", 5)
.text(y.tickFormat(5, "s"))
.clone(true)
.attr("fill", "#000")
.attr("stroke", "none")))
Insert cell
legend = g => g.append("g")
.selectAll("g")
.data(data.columns.slice(startCol,data.columns.length-endColDiff).reverse())
.enter().append("g")
.attr("transform", (d, i) => `translate(-40,${(i - (data.columns.length - startCol + endColDiff - 1) / 2) * 20})`)
.call(g => g.append("rect")
.attr("width", 18)
.attr("height", 18)
.attr("fill", z))
.call(g => g.append("text")
.attr("x", 24)
.attr("y", 9)
.attr("dy", "0.35em")
.text(d => d))
Insert cell
startCol = 13
Insert cell
endColDiff = 1
Insert cell
width = 986
Insert cell
height = 860
Insert cell
innerRadius = 199
Insert cell
outerRadius = Math.min(width, height) / 2
Insert cell
d3 = require("d3@5")
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