Public
Edited
Mar 17
Insert cell
Insert cell
popPyramidsCombined= {
const svg = d3.select(DOM.svg(width, height));
svg.append("g")
.attr("fill", d3.schemeSet1[1])
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", d => xM(d.male_census))
.attr("y", d => y(d.age))
.attr("width", d => xM(0) - xM(d.male_census))
.attr("height", y.bandwidth());
svg.append("g")
.style("fill-opacity", 0)
.attr("stroke", "black")
.attr("stroke-width", 2)
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", d => xM(d.male_trees))
.attr("y", d => y(d.age))
.attr("width", d => xM(0) - xM(d.male_trees))
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", d3.schemeSet1[0])
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", xF(0))
.attr("y", d => y(d.age))
.attr("width", d => xF(d.female_census) - xF(0))
.attr("height", y.bandwidth());
svg.append("g")
.style("fill-opacity", 0)
.attr("stroke", "black")
.attr("stroke-width", 2)
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", xF(0))
.attr("y", d => y(d.age))
.attr("width", d => xF(d.female_trees) - xF(0))
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "start")
.style("font", "10px sans-serif")
.selectAll("text")
.data(csv_data)
.enter().append("text")
.attr("x", d => xM(d.male_trees) + 4 - shiftx_values)
.attr("y", d => y(d.age) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.text(d => format(d.male_trees.toLocaleString()));
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "end")
.style("font", "10px sans-serif")
.selectAll("text")
.data(csv_data)
.enter().append("text")
.attr("x", d => xF(d.female_trees) - 4 + shiftx_values)
.attr("y", d => y(d.age) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.text(d => format(d.female_trees.toLocaleString()));
svg.append("text")
.attr("text-anchor", "end")
.attr("fill", "white")
.style("font", "10px sans-serif")
.attr("dy", "0.35em")
.attr("x", xM(0) - 4)
.attr("y", y(csv_data[0].age) + y.bandwidth() / 2)
.text("Male");
svg.append("text")
.attr("text-anchor", "start")
.attr("fill", "white")
.style("font", "10px sans-serif")
.attr("dy", "0.35em")
.attr("x", xF(0) + 4)
.attr("y", y(csv_data[0].age) + y.bandwidth() / 2)
.text("Female");
svg.append("g")
.call(xAxis);
svg.append("g")
.call(yAxis);
return svg.node();
}
Insert cell
popPyramidCensus = {
const svg = d3.select(DOM.svg(width, height));
svg.append("g")
.attr("fill", d3.schemeSet1[1])
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", d => xM(d.male_census))
.attr("y", d => y(d.age))
.attr("width", d => xM(0) - xM(d.male_census))
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", d3.schemeSet1[0])
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", xF(0))
.attr("y", d => y(d.age))
.attr("width", d => xF(d.female_census) - xF(0))
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "start")
.style("font", "10px sans-serif")
.selectAll("text")
.data(csv_data)
.enter().append("text")
.attr("x", d => xM(d.male_census) + 4 - shiftx_values)
.attr("y", d => y(d.age) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.text(d => format(d.male_census.toLocaleString()));
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "end")
.style("font", "10px sans-serif")
.selectAll("text")
.data(csv_data)
.enter().append("text")
.attr("x", d => xF(d.female_census) - 4 + shiftx_values)
.attr("y", d => y(d.age) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.text(d => format(d.female_census.toLocaleString()));
svg.append("text")
.attr("text-anchor", "end")
.attr("fill", "white")
.style("font", "10px sans-serif")
.attr("dy", "0.35em")
.attr("x", xM(0) - 4)
.attr("y", y(csv_data[0].age) + y.bandwidth() / 2)
.text("Male");
svg.append("text")
.attr("text-anchor", "start")
.attr("fill", "white")
.style("font", "10px sans-serif")
.attr("dy", "0.35em")
.attr("x", xF(0) + 4)
.attr("y", y(csv_data[0].age) + y.bandwidth() / 2)
.text("Female");
svg.append("g")
.call(xAxis);
svg.append("g")
.call(yAxis);
return svg.node();
}
Insert cell
popPyramidTrees = {
const svg = d3.select(DOM.svg(width, height));
svg.append("g")
.attr("fill", d3.schemeSet1[1])
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", d => xM(d.male_trees))
.attr("y", d => y(d.age))
.attr("width", d => xM(0) - xM(d.male_trees))
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", d3.schemeSet1[0])
.selectAll("rect")
.data(csv_data)
.enter().append("rect")
.attr("x", xF(0))
.attr("y", d => y(d.age))
.attr("width", d => xF(d.female_trees) - xF(0))
.attr("height", y.bandwidth());
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "start")
.style("font", "10px sans-serif")
.selectAll("text")
.data(csv_data)
.enter().append("text")
.attr("x", d => xM(d.male_trees) + 4 - shiftx_values)
.attr("y", d => y(d.age) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.text(d => format(d.male_trees.toLocaleString()));
svg.append("g")
.attr("fill", "black")
.attr("text-anchor", "end")
.style("font", "10px sans-serif")
.selectAll("text")
.data(csv_data)
.enter().append("text")
.attr("x", d => xF(d.female_trees) - 4 + shiftx_values)
.attr("y", d => y(d.age) + y.bandwidth() / 2)
.attr("dy", "0.35em")
.text(d => format(d.female_trees.toLocaleString()));
svg.append("text")
.attr("text-anchor", "end")
.attr("fill", "white")
.style("font", "10px sans-serif")
.attr("dy", "0.35em")
.attr("x", xM(0) - 4)
.attr("y", y(csv_data[0].age) + y.bandwidth() / 2)
.text("Male");
svg.append("text")
.attr("text-anchor", "start")
.attr("fill", "white")
.style("font", "10px sans-serif")
.attr("dy", "0.35em")
.attr("x", xF(0) + 4)
.attr("y", y(csv_data[0].age) + y.bandwidth() / 2)
.text("Female");
svg.append("g")
.call(xAxis);
svg.append("g")
.call(yAxis);
return svg.node();
}
Insert cell
shiftx_values = 20
Insert cell
shiftx = 40
Insert cell
format = d3.format(".1f")
Insert cell
csv_data = d3.csvParse(await FileAttachment("linkage1880_agebysex_stepII.csv").text())
Insert cell
xM = d3.scaleLinear()
//.domain([0, d3.max(csv_data, d => Math.max(d.female_trees, d.male_trees))])
.domain([0, 10])
.range([width / 2, margin.left])
Insert cell
xF = d3.scaleLinear()
.domain(xM.domain())
.range([width / 2 + shiftx, width - margin.right])
Insert cell
y = d3.scaleBand()
.domain(csv_data.map(d => d.age))
.range([height - margin.bottom, margin.top])
.padding(0.1)
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(g => g.append("g").call(d3.axisBottom(xM).ticks(width / 80, "s")))
.call(g => g.append("g").call(d3.axisBottom(xF).ticks(width / 80, "s")))
.call(g => g.selectAll(".domain").remove())
.call(g => g.selectAll(".tick:first-of-type").remove())
Insert cell
yAxis = g => g
.attr("transform", `translate(${xM(0)},0)`)
.call(d3.axisRight(y).tickSizeOuter(0))
.call(g => g.selectAll(".tick text").attr("fill", "black"))
Insert cell
height = csv_data.length * 25 + margin.top + margin.bottom
Insert cell
margin = ({top: 10, right: 0, bottom: 20, left: 0})
Insert cell
d3 = require("d3@5")
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