Published
Edited
Jul 21, 2020
5 stars
Insert cell
Insert cell
{
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

svg
.append("g")
.attr("id", "comets")
.selectAll("path")
.data([aggregate].concat(data))
.join("path")
.style("opacity", (_, i) => (!i ? 1 : .5))
.attr("d", comet())
.attr("fill", (d, i) =>
!i ? "#000" : color(Math.log(d.endweight / d.startweight))
)
.append("title")
.text(d => `${d.state} - ${d.birthweight}`);

const axes = svg.append("g");
axes
.append("g")
.attr("transform", `translate(0, ${y.range()[0]})`)
.call(d3.axisBottom(x).tickFormat(tickFormat))
.append("text")
.attr("transform", `translate(${x.range()[1] + 20}, 0)`)
.style("fill", "black")
.text("weight");

axes
.append("g")
.attr("transform", `translate(${x.range()[0]}, 0)`)
.call(d3.axisLeft(y).tickFormat(tickFormat))
.append("text")
.attr("transform", `translate(0, ${y.range()[1] - 15})`)
.style("fill", "black")
.text("value");

return svg.node();
}
Insert cell
import { trail } from "@fil/trail-marks"
Insert cell
function comet(context) {
const size = d3.scaleLinear().range([1.5, 7]);
const tr = trail()
.x(d => x(d[0]))
.y(d => y(d[1]))
.size(d => size(d[2]))
.defined(d => true)
.context(context);
return function(d) {
const start = [d.startweight, d.startvalue, 0],
end = [d.endweight, d.endvalue, 1];
return tr([start, end]);
};
}
Insert cell
aggregate = ({
state: "aggregate",
startweight: d3.mean(data, d => d.startweight),
endweight: d3.mean(data, d => d.endweight),
startvalue:
d3.sum(data, d => d.startweight * d.startvalue) /
d3.sum(data, d => d.startweight),
endvalue:
d3.sum(data, d => d.endweight * d.endvalue) / d3.sum(data, d => d.endweight)
})
Insert cell
height = 500
Insert cell
x = d3.scaleLog(
[400, d3.max(data, d => d.endweight)],
[40, Math.min(width, 600) - 40]
)
Insert cell
y = d3.scaleLog([0.9, 1000], [height - 40, 40])
Insert cell
tickFormat = d => (["1", "2", "5"].includes(String(d)[0]) ? d : "")
Insert cell
diff = d3.max(data, d => Math.abs(Math.log(d.endweight / d.startweight)))
Insert cell
color = d3
.scaleLinear()
.domain([-diff, 0, diff])
.range(['orange', 'grey', 'blue'])
Insert cell
data = d3.csvParse(await FileAttachment("data.csv").text(), d3.autoType)
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