Published
Edited
Aug 24, 2020
Insert cell
Insert cell
Insert cell
html`<svg><g>${sortOrder.map((l, i) => `<rect x=0 y=${i*18 + 4} width=40 height=10 style="fill: ${stringColor[sortOrder.indexOf(l)]}"/><text x=60 y=${i*18 + 15}>${l}</text>`)}</g></svg>`;
Insert cell
width= 965
Insert cell
stringColor =["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"]
Insert cell
sortOrder = ["Kazakhstan","Kyrgyzstan","Tajikistan","Turkmenistan","Uzbekistan"];
Insert cell
fieldName = "size"
Insert cell
colsv = d3.dsvFormat(";");
Insert cell
fileData = colsv.parseRows(await FileAttachment("FigureAB-IPv4addresses-yearly.csv").text())
Insert cell
dates = fileData[1].map((d,i) => i > 0 && new Date(d) || null).filter(d => d)
Insert cell
dd = fileData.slice(2, fileData.length).flatMap(d => {
return d.slice(1, d.length).map((dd,i) => ({ name: d[0], date: dates[i], [fieldName]: dd })) })
Insert cell
data = {
const data = dd
.map(d => ({ ...d, date: new Date(d.date)}))
.sort((a,b) => sortOrder.indexOf(a.name) < sortOrder.indexOf(b.name) && -1 || +1 );
const dates = Array.from(d3.group(data, d => +d.date).keys()).sort(d3.ascending);
return {
dates: dates.map(d => new Date(d)),
series: d3.groups(data, d => d.name).map(([name, values]) => {
const value = new Map(values.map(d => [+d.date, d[fieldName]]));
return {name, values: dates.map(d => value.get(d))};
})
};
}
Insert cell
pdata = data.series.map(r => r.values.map((d,i) => ({ date: data.dates[i], value: d})))
Insert cell
line_si = d3.line()
.defined(d => !isNaN(d.value))
.x(d => x(d.date))
.y(d => y(d.value))
Insert cell
x = d3.scaleUtc()
.domain(d3.extent([ ...pdata[0], {date: new Date("2021-07-15")}], d => d.date))
.range([margin.left, width - margin.right])
Insert cell
d3.max(pdata.flatMap(p => p), d => Number(d.value))
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(pdata.flatMap(p => p), d => Number(d.value))]).nice()
// .domain([0, 3500000]).nice()
.range([height - margin.bottom, margin.top])
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).ticks(width / 80).tickSizeOuter(0))
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y))
.call(g => g.select(".domain").remove())
.call(g => g.select(".tick:last-of-type text").clone()
.attr("x", 3)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(pdata[0].y))
Insert cell
margin = ({top: 20, right: 30, bottom: 30, left: 40})
Insert cell
height = 500
Insert cell
d3 = require("d3@5", "d3-array@2")
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