Public
Edited
May 25, 2020
Insert cell
md`# Learning d3 - Line charts
## Population of the United Kingdom
### with dynamic data from Wikidata via the WDQS`
Insert cell
md`### Load the data from the WDQS `
Insert cell
{
const xValue = d => d.date.value;
const xScale = d3.scaleLinear()
.domain(d3.extent(data, xValue))
.range([0, innerWidth])

return xScale(1966)
}
Insert cell
chart = {
const chart = DOM.svg(800, 500);
const svg = d3.select(chart);
const width = +svg.attr("width");
const height = +svg.attr("height");
const xValue = d => d.date.value;
const yValue = d => d.population.value;
const margin = { top: 30, right: 20, bottom:60, left: 70 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const xScale = d3.scaleUtc()
.domain(d3.extent(data, xValue))
.range([0, innerWidth])
.nice();

const yScale = d3.scaleLinear()
.domain(d3.extent(data, yValue))
.range([innerHeight, 0])
.nice();
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`)
// const xAxisTickFormat = number => d3.format(".3s")(number)
// .replace("G", "B");
const xAxis = d3.axisBottom(xScale)
// .tickFormat(xAxisTickFormat)
.tickSize(-innerHeight)
.tickPadding(10);
const yAxis = d3.axisLeft(yScale)
.tickSize(-innerWidth);
const yAxisG = g.append("g").call(yAxis);
yAxisG.selectAll(".domain")
.remove(); // remove the left axis top and bottom ticks; the css selector to remove were found by inspecting the DOM of the rendered bar chart
yAxisG.append("text")
.attr("x", -innerHeight / 2) // note these are reversed because of the rotation below
.attr("y", -60 )
.attr("text-anchor", "middle")
.attr("fill", "black")
.text("Population")
.attr("transform", "rotate(-90)")
.attr("class", "yAxisLabel");

const xAxisG = g.append("g").call(xAxis)
.attr("transform", `translate(0,${innerHeight})`);
xAxisG.select(".domain").remove();
xAxisG.append("text")
.attr("x", innerWidth / 2)
.attr("y", 40)
.attr("fill", "black")
.text("Year")
.attr("class", "xAxisLabel");
const lineGenerator = d3.line()
.x(d => xScale(xValue(d)))
.y(d => yScale(yValue(d)));
g.append("path")
.attr("class", "line-path")
.attr("d", lineGenerator(data));
g.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => xScale(xValue(d)))
.attr("cy", d => yScale(yValue(d)))
.attr("r", 4)
// .append("title").text(d => xValue(d).getFullYear() );
// why can't I combine the functions if I use arrow function?
.append("title").text(function(d) { return `${xValue(d).getFullYear()}: ${yValue(d)}` } );

g.append("text")
.attr("x", 40)
.attr("y", -10)
.text(`Line chart of United Kingdom population by year`);

return chart;

}

Insert cell
md`# Appendix`
Insert cell
md`Style Sheet`
Insert cell
html`<style>
circle {
fill: black;
opacity: 1;
}
text {
font-size: 1.45m;
font-family: sans-serif;
}
.tick line {
stroke: #C0C0BB;
}
.yAxisLabel {
font-size: 1.5em;
}
.xAxisLabel {
font-size: 1.5em;
}

.line-path {
fill: none;
stroke: red;
stroke-width: 2px;
}
</style>`
Insert cell
md`Include Libraries`
Insert cell
d3 = require("d3");
Insert cell
md`Load data from the Wikidata Query Service (WDQS)`
Insert cell
sparql = ` # place your SPARQL query between the backticks
SELECT ?date (AVG(?pop) AS ?population) WHERE {
wd:Q145 p:P1082 [
ps:P1082 ?pop ;
pq:P585 ?date
]
}
GROUP BY ?date
ORDER BY ASC (?date)

`; // place your SPARQL query between the backticks
Insert cell
json = fetch(`https://query.wikidata.org/sparql?query=${encodeURIComponent(sparql)}`, {headers: {accept: "application/sparql-results+json"}}).then(response => response.json())
Insert cell
md`Clean the data`
Insert cell
json.results.bindings.forEach( d => {
d.date.value = new Date(d.date.value);
}); // convert the population & area from string to number

Insert cell
data = json.results.bindings;
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