Public
Edited
Nov 18, 2022
Insert cell
Insert cell
data = d3.csvParse(
`source,target,value
Auto Sales,Total Auto Revenue,17785
Regulatory Credits,Total Auto Revenue,286
Auto Leasing,Total Auto Revenue,621
Total Auto Revenue,Revenue,18692
Energy Gen. & Storage,Revenue,1117
Services & Other,Revenue,1645
Revenue,Cost of Revenue,16072
Revenue,Gross Profit,5382
Cost of Revenue,Total Auto Cost of Revenue,13480
Cost of Revenue,Energy Gen. & Storage Cost of Revenue,1013
Cost of Revenue,Services & Other Cost of Revenue,1579
Gross Profit,Operating Expenses,1694
Operating Expenses,Research & Development,733
Operating Expenses,SG&A,961
Gross Profit,Operating Profit,3688
`,
d3.autoType

)
Insert cell
Insert cell
Insert cell
Insert cell

sankey = {
const svg = d3
.create("svg")
.attr("height", dimensions.height)
.attr("width", dimensions.width)
.attr("overflow", "visible");

const chart = svg
.append("g")
.attr("transform", `translate(${dimensions.margins},${dimensions.margins})`)
.attr("height", dimensions.height - dimensions.margins * 2)
.attr("width", dimensions.width - dimensions.margins * 2)
.attr("overflow", "visible");
const adjustor = (i) => {
return 0;
};
const nodes = chart
.append("g")
.selectAll("rect")
.data(sankeyData.nodes)
.join("rect")
.attr("x", (d) => d.x0)
.attr("y", (d) => d.y0)
.attr("fill", (d) => colorScale(d.name))
.attr("height", (d) => d.y1 - d.y0)
.attr("width", (d) => d.x1 - d.x0);

const links = chart
.append("g")
.attr("fill", "none")
.attr("stroke", "#000")
.attr("stroke-opacity", 0.1)
.selectAll("path")
.data(sankeyData.links)
.join("path")
.attr("d", d3Sankey.sankeyLinkHorizontal())
.attr("stroke-width", function (d) {
return d.width;
});

const labelNames = chart
.append("g")
.selectAll("text")
.data(sankeyData.nodes)
.join("text")
.text((d) => d.name)
.attr("class", (d) => d.depth)
.attr("x", (d) => d3.mean([d.x0, d.x1]))
.attr("y", (d) => d3.mean([d.y0, d.y1]))
.attr("text-anchor", "middle")
.attr("dominant-baseline", "middle")
.attr("fill", (d) => (d.y1 - d.y0 < 20 ? "black" : "white"))
.attr("font-family", "helvetica")
.attr("font-weight", "400")
.attr("font-size", "18")
.style("text-shadow", ".5px .5px 2px #000");

const labelValues = chart
.append("g")
.selectAll("text")
.data(sankeyData.nodes)
.join("text")
.text((d) => `${d3.format("~s")(d.value)}`)
// .attr("x", (d) => d3.mean([d.x0, d.x1]))
.attr("x", (d) => d.x1)
.attr("y", (d) => d3.mean([d.y0, d.y1]))
.attr("dx", (d) => `${2}px`)
.attr("text-anchor", "left")
.attr("dominant-baseline", "middle")
// .attr("fill", (d) => (d.y1 - d.y0 < 20 ? "black" : "white"))
.attr("font-family", "helvetica")
.attr("font-weight", "500")
.attr("font-size", "20")
.style("text-shadow", ".5px .5px 2px #222");

return svg.node();
};
Insert cell
// process and manipulate the sankeyData object
sankeyData = {
const sankeyData = { nodes: [], links: [] };
//sankey Arguments
data.forEach((d) => {
const nodesList = sankeyData.nodes.map((n) => n.name);
if (!nodesList.includes(d.source)) {
sankeyData.nodes.push({ name: d.source });
}
if (!nodesList.includes(d.target)) {
sankeyData.nodes.push({ name: d.target });
}
sankeyData.links.push({
source: d.source,
target: d.target,
value: d.value
});
});
sankeyData.links.forEach((l, lNdx) => {
sankeyData.links[lNdx].source = sankeyData.nodes.indexOf(
sankeyData.nodes.find((n) => n.name === l.source)
);
sankeyData.links[lNdx].target = sankeyData.nodes.indexOf(
sankeyData.nodes.find((n) => n.name === l.target)
);
});
const sankeyViz = d3Sankey
.sankey()
.nodes(sankeyData.nodes)
.links(sankeyData.links)
.nodeAlign(d3Sankey.sankeyLeft)
.nodeWidth(200)
.extent([
[dimensions.margins, dimensions.margins],
[
dimensions.width - dimensions.margins * 2,
dimensions.height - dimensions.margins * 2
]
]);
return sankeyViz();
}
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