Public
Edited
Nov 29, 2023
Fork of Scatter plot
Insert cell
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("width", width).attr("height", height);

// Axis
svg
.append("g")
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(xAxis);

svg.append("g").attr("transform", `translate(${margin.left}, 0)`).call(yAxis);

// Bubbles
const bubbles = svg
.selectAll("bubbles")
.data(data)
.enter()
.append("circle")
.attr("cx", (d) => xScale(d["Income per person"]))
.attr("cy", (d) => yScale(d["Life expectancy "]))
// .attr("r", 4.2)
.attr("r", (d) => radiusScale(d.Population))
.attr("fill", (d) => findColors(d.region))
.style("fill-opacity", 0.74)
.attr("stroke", "#555")
.on("mousemovet", function (event, d, index) {
toolTip
.style("left", event.pageX + 0 + "px")
.style("top", event.pageY - 52 + "px")
.style("display", "block")
.html(`${d.name}`);

d3.select(this).style("stroke-width", 3);
})
.on("mouseout", function () {
toolTip.style("display", "none");
d3.select(this).style("stroke-width", 1);
});

// Tooltip
const toolTip = d3.select("body").append("div").attr("class", "toolTip");

getLegend(svg, "vertical", 18, 7, 5, domains.length);

return svg.node();
}
Insert cell
Insert cell
findColors = (region) => {
let color;
if (region === "asia") {
color = "#ff5872";
} else if (region === "europe") {
color = "#ffe700";
} else if (region === "africa") {
color = "#00d5e9";
} else if (region === "americas") {
color = "#7fea00";
}
return color;
}
Insert cell
Insert cell
yAxis = d3.axisLeft(yScale) //.ticks(5)
Insert cell
Insert cell
xAxis = d3
.axisBottom(xScale)
.tickFormat(d3.format("~s")) //숫자를 간결하게 표현하기 위한 포매팅 방식 (K, M)
.tickValues([500, 1000, 2000, 4000, 8000, 16000, 32000, 64000])
Insert cell
Insert cell
yScale = d3
.scaleLinear()
.domain(d3.extent(data, (d) => d["Life expectancy "]))
.range([height - margin.bottom, margin.top])
Insert cell
xScale = d3
.scaleLog()
// .domain(d3.extent(data, (d) => d["Income per person"]))
.domain([500, d3.max(data, (d) => d["Income per person"])])
// .domain([0, d3.max(data, (d) => d["Income per person"])])
.range([margin.left, width - margin.right])
Insert cell
radiusScale = d3
.scaleSqrt()
.domain([0, d3.max(data, (d) => d.Population)])
.range([0, 50])
Insert cell
margin = ({ top: 20, right: 100, bottom: 60, left: 60 })
Insert cell
height = 540
Insert cell
Insert cell
Insert cell
[...new Set(data.map((d) => d.region))]
Insert cell
Insert cell
data = life_expectancy
.map((d) => {
d["Income per person"] = gdp_per_capita.find((g) => g.name === d.name)[
"Income per person"
];
d.Population = population.find((p) => p.name === d.name).Population;
d.region = region.find((r) => r.name === d.name).four_regions;
return d;
})
.sort((a, b) => b.Population - a.Population)
Insert cell
life_expectancy = d3
.csvParse(
await FileAttachment("gapminder_lifeExpectancy.csv").text(),
d3.autoType
)
.filter((d) => d.time === 2022)
Insert cell
gdp_per_capita = d3
.csvParse(
await FileAttachment("gapminder_gdpPerCapita.csv").text(),
d3.autoType
)
.filter((d) => d.time === 2022)
Insert cell
population = d3
.csvParse(
await FileAttachment("gapminder_population.csv").text(),
d3.autoType
)
.filter((d) => d.time === 2022)
Insert cell
region = d3.csvParse(
await FileAttachment("gapminder_region.csv").text(),
d3.autoType
)
Insert cell
// Vertical and horizontal Legend
function getLegend(svg, direction, key_size, item_padding, text_x_offset, classes){
const legend_height = classes * (key_size + item_padding);

// Legend as a group
const legend = svg.append("g")
// Apply a translation to the entire group
.attr("transform", `translate(${width/1.09}, ${legend_height})`)
// Boxes
legend
.selectAll("boxes")
.data(domains)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", (d, i) => (i * (key_size + item_padding)))
.attr("width", key_size)
.attr("height", key_size)
.style("fill", (d) => findColors(d));
// Labels
legend
.selectAll("labels")
.data(domains)
.enter()
.append("text")
.attr("x", key_size)
.attr("y", (d, i) => i * (key_size + item_padding))
.attr("dx", text_x_offset)
.attr("dy", ".5em")
.text((d) => d)
.attr("text-anchor", "left")
.style("alignment-baseline", "middle")
.style("font-family", "sans-serif")
.style("font-size", key_size+"px");

}

Insert cell
domains = ["asia", "americas","africa","europe"];
Insert cell
Insert cell
html`<style>

.toolTip {
position: absolute;
background-color: rgba(255,255,255,1);
padding: 4px 10px;
font-size: 21px;
border: 1px solid #333;
border-radius: 8px;
font-family: arial;
font-weight: 500;
line-height: 1.2;
letter-spacing: -.5px;
}
</style>`
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