Public
Edited
May 1
Insert cell
Insert cell
Insert cell
data@1.csv
Type Table, then Shift-Enter. Ctrl-space for more options.

Insert cell
import {SankeyChart} from "@d3/sankey-component"
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
{
// Ref https://observablehq.com/@d3/streamgraph/2
// Prepare data: group by Year and Company
const nested = d3.rollups(
data1,
v => v.length,
d => d.Year,
d => d.Company
);

const companies = ["Sony", "Nintendo", "Microsoft", "PC", "SEGA"];
const years = Array.from(new Set(data1.map(d => d.Year))).sort(d3.ascending);

// Reshape to a uniform stacked format: each row = { year, Sony: X, Nintendo: Y, ... }
const stackedData = years.map(year => {
const entry = { year };
const gamesPerYear = nested.find(([y]) => y === year);
if (gamesPerYear) {
gamesPerYear[1].forEach(([company, count]) => {
entry[company] = count;
});
}
// Ensure every company has an entry
companies.forEach(c => {
if (!entry.hasOwnProperty(c)) entry[c] = 0;
});
return entry;
});

// Set up dimensions
const width = 900, height = 500;
const margin = { top: 30, right: 30, bottom: 50, left: 60 };

// Scales
const x = d3.scaleLinear()
.domain(d3.extent(stackedData, d => d.year))
.range([margin.left, width - margin.right]);

const stacked = d3.stack()
.keys(companies)
.offset(d3.stackOffsetSilhouette)(stackedData);

const y = d3.scaleLinear()
.domain([
d3.min(stacked, layer => d3.min(layer, d => d[0])),
d3.max(stacked, layer => d3.max(layer, d => d[1]))
])
.range([height - margin.bottom, margin.top]);

const color = d3.scaleOrdinal()
.domain(companies)
.range(["steelblue", "red", "green", "orange", "purple"]);

// Area generator
const areaGen = d3.area()
.x((d, i) => x(stackedData[i].year))
.y0(d => y(d[0]))
.y1(d => y(d[1]))
.curve(d3.curveBasis);

// Create SVG
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height);

// Draw layers
svg.selectAll("path")
.data(stacked)
.join("path")
.attr("fill", d => color(d.key))
.attr("d", areaGen)
.append("title")
.text(d => d.key);

// Axes
svg.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).ticks(10).tickFormat(d3.format("d")));

// Add the Y axis, but hide the labels
svg.append("g")
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).tickFormat(() => ""))
.selectAll("line")
.attr("stroke-opacity", 0.7);

// Title
svg.append("text")
.attr("x", width / 2)
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.style("font-size", "16px")
.text("Streamgraph of Top Games Per Year by Console Manufacturer");

// Legend
const legend = svg.append("g")
.attr("transform", `translate(${width - margin.right - 100},${margin.top})`);

companies.forEach((company, i) => {
const g = legend.append("g").attr("transform", `translate(0, ${i * 20})`);
g.append("rect").attr("width", 15).attr("height", 15).attr("fill", color(company));
g.append("text")
.attr("x", 20)
.attr("y", 12)
.style("font-size", "12px")
.text(company);
});
return svg.node();
}

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