viewof svg = {
const margin = {top: 40, right: 40, bottom: 60, left: 70},
width = 800,
height = 500;
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const data = filteredData.filter(d => !isNaN(d.Profit) && !isNaN(d.Sales))
.map(d => ({
Profit: +d.Profit,
Sales: +d.Sales,
Market: d.Market
}));
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.style("font-family", "sans-serif");
const g = svg.append("g")
.attr("transform", `translate(${margin.left},${margin.top})`);
const x = d3.scaleLinear()
.domain(d3.extent(data, d => d.Profit)).nice()
.range([0, innerWidth]);
const y = d3.scaleLinear()
.domain(d3.extent(data, d => d.Sales)).nice()
.range([innerHeight, 0]);
const color = d3.scaleOrdinal()
.domain([...new Set(data.map(d => d.Market))])
.range(d3.schemeTableau10);
g.append("g")
.attr("class", "grid")
.call(d3.axisLeft(y).tickSize(-innerWidth).tickFormat(""))
.selectAll("line")
.attr("stroke", "#ccc")
.attr("stroke-opacity", 0.3);
g.append("g")
.attr("transform", `translate(0,${innerHeight})`)
.call(d3.axisBottom(x));
g.append("g")
.call(d3.axisLeft(y));
svg.append("text")
.attr("text-anchor", "middle")
.attr("x", margin.left + innerWidth / 2)
.attr("y", height - 15)
.attr("font-size", "14px")
.text("Profit");
svg.append("text")
.attr("text-anchor", "middle")
.attr("x", -margin.top - innerHeight / 2)
.attr("y", 20)
.attr("transform", "rotate(-90)")
.attr("font-size", "14px")
.text("Sales");
g.selectAll("circle")
.data(data)
.join("circle")
.attr("cx", d => x(d.Profit))
.attr("cy", d => y(d.Sales))
.attr("r", 4)
.attr("fill", d => color(d.Market))
.attr("opacity", 0.6)
.attr("stroke", "white")
.attr("stroke-width", 0.5);
const legend = svg.append("g")
.attr("transform", `translate(${width - margin.right - 120}, ${margin.top})`);
const markets = color.domain();
markets.forEach((market, i) => {
const row = legend.append("g")
.attr("transform", `translate(0, ${i * 20})`);
row.append("rect")
.attr("width", 12)
.attr("height", 12)
.attr("fill", color(market));
row.append("text")
.attr("x", 18)
.attr("y", 10)
.attr("font-size", "12px")
.text(market);
});
return svg.node();
}