Skip to content

Instantly share code, notes, and snippets.

@Madhusuthanan-B
Last active March 31, 2024 17:58
Show Gist options
  • Save Madhusuthanan-B/9a8c00b6fe98284c625c6d31d1be3061 to your computer and use it in GitHub Desktop.
Save Madhusuthanan-B/9a8c00b6fe98284c625c6d31d1be3061 to your computer and use it in GitHub Desktop.
Paretto chart example
const ParetoChart = (function () {
let svg, x, yRevenue, yPercentage, color;
const margin = { top: 20, right: 80, bottom: 30, left: 60 },
width = 600 - margin.left - margin.right,
height = 400 - margin.top - margin.bottom;
function init(data) {
data.sort((a, b) => d3.descending(a.revenue, b.revenue));
let totalRevenue = d3.sum(data, (d) => d.revenue);
let cumulativePercentage = 0;
data.forEach((d) => {
d.cumulativeRevenue = cumulativePercentage += d.revenue;
d.cumulativePercentage = (d.cumulativeRevenue / totalRevenue) * 100;
});
svg = d3
.select("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
x = d3
.scaleBand()
.range([0, width])
.domain(data.map((d) => d.product))
.padding(0.2);
yRevenue = d3
.scaleLinear()
.domain([0, d3.max(data, (d) => d.revenue)])
.range([height, 0]);
yPercentage = d3.scaleLinear().domain([0, 100]).range([height, 0]);
color = d3
.scaleOrdinal()
.domain(data.map((d) => d.product))
.range(d3.schemeTableau10);
drawAxes();
drawAxisLabels();
drawBars(data);
drawLine(data);
drawDottedLines();
}
function drawAxes() {
svg
.append("g")
.attr("transform", `translate(0,${height})`)
.call(d3.axisBottom(x));
svg.append("g").call(d3.axisLeft(yRevenue));
svg
.append("g")
.attr("transform", `translate(${width}, 0)`)
.call(d3.axisRight(yPercentage));
}
function drawAxisLabels() {
svg
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 0 - margin.left)
.attr("x", 0 - height / 2)
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Revenue");
svg
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", width + margin.right - 20)
.attr("x", 0 - height / 2)
.attr("dy", "1em")
.style("text-anchor", "middle")
.text("Cumulative Percentage (%)");
}
function drawBars(data) {
svg
.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("x", (d) => x(d.product))
.attr("y", (d) => yRevenue(d.revenue))
.attr("width", x.bandwidth())
.attr("height", (d) => height - yRevenue(d.revenue))
.attr("fill", (d) => color(d.product))
.attr("class", (d) =>
d.cumulativePercentage <= 80 ? "vital" : "trivial"
);
}
function drawLine(data) {
svg
.append("path")
.datum(data)
.attr("fill", "none")
.attr("stroke", "red")
.attr("stroke-width", 1.5)
.attr(
"d",
d3
.line()
.x((d) => x(d.product) + x.bandwidth() / 2)
.y((d) => yPercentage(d.cumulativePercentage))
);
}
function drawDottedLines() {
svg
.append("line")
.style("stroke", "blue")
.style("stroke-width", 1)
.style("stroke-dasharray", "3, 3")
.attr("x1", 0)
.attr("y1", yPercentage(80))
.attr("x2", width)
.attr("y2", yPercentage(80));
}
return {
init: init,
};
})();
const data = [
{ product: "Smartphone", revenue: 50000 },
{ product: "Laptop", revenue: 75000 },
{ product: "Tablet", revenue: 30000 },
{ product: "Smartwatch", revenue: 20000 },
{ product: "Headphones", revenue: 15000 },
];
ParetoChart.init(data);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment