{
const margin = {top: 40, right: 140, bottom: 40, left: 60};
const width = 900;
const height = 500;
const clean = aiddata
.filter(d => d.purpose !== "Sectors not specified")
.map(d => ({
year : +d.yearInt,
purpose: d.purpose.trim(),
amount : +d.amount
}));
const totals = d3.rollup(
clean,
v => d3.sum(v, d => d.amount),
d => d.purpose
);
const top10 = d3.sort(totals, (a,b) => d3.descending(a[1], b[1]))
.slice(0,10)
.map(d => d[0]);
const byYearPurpose = d3.rollups(
clean.filter(d => top10.includes(d.purpose)),
v => d3.sum(v, d => d.amount),
d => d.year,
d => d.purpose
);
const series = byYearPurpose.map(([year, arr]) => {
const purposeMap = new Map(arr);
const row = { year };
top10.forEach(p => row[p] = purposeMap.get(p) ?? 0);
return row;
}).sort((a, b) => d3.ascending(a.year, b.year));
const stack = d3.stack().keys(top10);
const layers = stack(series);
const x = d3.scaleLinear()
.domain(d3.extent(series, d => d.year))
.range([margin.left, width - margin.right]);
const y = d3.scaleLinear()
.domain([0, d3.max(layers, L => d3.max(L, d => d[1]))])
.nice()
.range([height - margin.bottom, margin.top]);
const color = d3.scaleOrdinal()
.domain(top10)
.range(d3.schemeTableau10);
const area = d3.area()
.x(d => x(d.data.year))
.y0(d => y(d[0]))
.y1(d => y(d[1]));
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height);
svg.append('g')
.selectAll('path')
.data(layers)
.join('path')
.attr('fill', d => color(d.key))
.attr('d', area)
.append('title')
.text(d => d.key);
svg.append('g')
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x).ticks(10).tickFormat(d3.format('d')))
.call(g => g.select('.domain').remove());
svg.append('g')
.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y).ticks(5, '~s'))
.call(g => g.select('.domain').remove());
const legend = svg.append('g')
.attr('font-size', 10)
.attr('transform', `translate(${width - margin.right + 10}, ${margin.top})`);
top10.forEach((p, i) => {
legend.append('rect')
.attr('x', 0)
.attr('y', i * 14)
.attr('width', 10)
.attr('height', 10)
.attr('fill', color(p));
legend.append('text')
.attr('x', 14)
.attr('y', i * 14 + 9)
.text(p);
});
return svg.node();
}