Public
Edited
Dec 12, 2023
Insert cell
Insert cell
data = FileAttachment("csvtable.csv").csv()

Insert cell
data2 = data.sort((a, b) => d3.ascending(parseInt(a.Year), parseInt(b.Year)));
Insert cell
height = 500

Insert cell
margin = ({ top: 80, right: 160, bottom: 50, left: 40 })
Insert cell
viewBox = [-20, -10, width + 30, height + 30]
Insert cell
x = d3
// TODO: create scale for x axis
.scaleBand()
.domain(data.map(d => d.Year))
.range([margin.left, width - margin.right])
.padding(0.1);
Insert cell
y = d3
// TODO: create scale for y axis
.scaleLinear()
.domain([0, 42])
.range([height - margin.bottom, margin.top])
Insert cell
table = {
// create the container SVG element
const svg = d3.create("svg").attr("viewBox", viewBox);

// position and populate the x-axis
svg
.append("g")
.call(d3.axisBottom(x))
.attr("transform", `translate(0, ${height - margin.bottom})`)

const barWidth = 20;
function showTooltip(event, d) {
const svgRect = svg.node().getBoundingClientRect(); // Get the SVG element's position

const tooltip = svg.append("foreignObject")
.attr("x", event.clientX - svgRect.left + 5) // Adjust the x-coordinate
.attr("y", event.clientY - svgRect.top - 30) // Adjust the y-coordinate
.attr("width", 200)
.attr("height", 60);

const tooltipDiv = tooltip.append("xhtml:div")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "5px")
.style("border-radius", "5px")
.text(`Non-Pregnant: ${d["Non-Pregnant (Aged 15-49)"]} %`);
}

// Function to hide tooltip
function hideTooltip() {
d3.select("foreignObject").remove();
}
// position and populate the y-axis
svg
.append("g")
.call(d3.axisLeft(y))
.attr("transform", `translate(${margin.left}, 0)`)
svg
.selectAll("rect")
.data(data2)
.enter()
.append("rect")
.attr("x", d => x(d.Year))
.attr("y", d => y(parseFloat(d["Non-Pregnant (Aged 15-49)"])))
.attr("width", x.bandwidth()/2)
.attr("height", d => height - margin.bottom - y(parseFloat(d["Non-Pregnant (Aged 15-49)"])))
.attr("fill", "steelblue")
.on("mouseover", function (event, d) {
d3.select(this).attr("fill", "lightsteelblue");
showTooltip(event,d);
})
.on("mouseout", function (event, d) {
d3.select(this).attr("fill", "steelblue");
hideTooltip();
});

// Create bars for Pregnant (positioned next to Non-Pregnant bars)
svg
.selectAll("rect.pregnant")
.data(data2)
.enter()
.append("rect")
.attr("x", d => x(d.Year) + x.bandwidth()/2) // Adjust the position based on the bar width
.attr("y", d => y(parseFloat(d["Pregnant (Aged 15-49)"])))
.attr("width", x.bandwidth()/2)
.attr("height", d => height - margin.bottom - y(parseFloat(d["Pregnant (Aged 15-49)"])))
.attr("fill", "orange")
.on("mouseover", function (event, d) {
d3.select(this).attr("fill", "lightsalmon");
showTool(event,d);
})
.on("mouseout", function (event, d) {
d3.select(this).attr("fill", "orange");
hideTool();
});

function showTool(event, d) {
const svgRect = svg.node().getBoundingClientRect(); // Get the SVG element's position

const tooltip = svg.append("foreignObject")
.attr("x", event.clientX - svgRect.left + 5) // Adjust the x-coordinate
.attr("y", event.clientY - svgRect.top - 30) // Adjust the y-coordinate
.attr("width", 180)
.attr("height", 60);

const tooltipDiv = tooltip.append("xhtml:div")
.style("background-color", "white")
.style("border", "1px solid black")
.style("padding", "5px")
.style("border-radius", "5px")
.text(`Pregnant: ${d["Pregnant (Aged 15-49)"]} %`);
}

// Function to hide tooltip
function hideTool() {
d3.select("foreignObject").remove();
}

const legend = svg
.append("g")
.attr("class", "legend")
.attr("transform", `translate(${width - 100}, 150)`); // Adjust the position

legend
.append("text")
.text("Legend")
.attr("x", -5) // Adjust the horizontal position
.attr("y", -60) // Adjust the vertical position
.attr("font-size", "16px") // Adjust the font size
.style("font-weight", "bold");

legend
.append("rect")
.attr("x", -40)
.attr("y", -40)
.attr("width", 10)
.attr("height", 10)
.attr("fill", "steelblue");

legend
.append("text")
.attr("x", -25)
.attr("y", -30)
.text("Non-Pregnant");

// Create legend for Pregnant
legend
.append("rect")
.attr("x", -40)
.attr("y", -20)
.attr("width", 10)
.attr("height", 10)
.attr("fill", "orange");

legend
.append("text")
.attr("x", -25)
.attr("y", -10)
.text("Pregnant");

svg
.append("text")
.attr("x", width / 2)
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.style("font-size", "20px")
.style("font-weight", "bold")
.text("Global Percentages of Anemic Women (Aged 15-49)");

svg
.append("text")
.attr("x", width / 2 - 40) // Center the label horizontally
.attr("y", height ) // Adjust the vertical position
.attr("text-anchor", "middle")
.attr("font-size", "16px") // Adjust the font size as needed
.text("Year");

svg
.append("text")
.attr("transform", "rotate(-90)") // Rotate the label for the y-axis
.attr("x", -height / 2 ) // Center the label vertically
.attr("y", 10) // Adjust the horizontal position
.attr("text-anchor", "middle")
.attr("font-size", "16px") // Adjust the font size as needed
.text("Global Percentage (%)"); // Change the label text as needed

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