Density contours

This chart shows the relationship between idle and eruption times for the Old Faithful geyser in Yellowstone National Park.

// Specify the dimensions of the chart.
const width = 928;
const height = 600;
const marginTop = 20;
const marginRight = 30;
const marginBottom = 30;
const marginLeft = 40;

// Create the horizontal and vertical scales.
const x = d3.scaleLinear()
    .domain(d3.extent(faithful, (d) => d.waiting)).nice()
    .rangeRound([marginLeft, width - marginRight]);

const y = d3.scaleLinear()
    .domain(d3.extent(faithful, (d) => d.eruptions)).nice()
    .rangeRound([height - marginBottom, marginTop]);

// Compute the density contours.
const contours = d3.contourDensity()
    .x((d) => x(d.waiting))
    .y((d) => y(d.eruptions))
    .size([width, height])
    .bandwidth(30)
    .thresholds(30)
  (faithful);

// Create the SVG container.
const svg = d3.create("svg")
    .attr("width", width)
    .attr("height", height)
    .attr("viewBox", [0, 0, width, height])
    .attr("style", "max-width: 100%; height: auto;");

// Append the axes.
svg.append("g")
    .attr("transform", `translate(0,${height - marginBottom})`)
    .call(d3.axisBottom(x).tickSizeOuter(0))
    .call((g) => g.select(".domain").remove())
    .call((g) => g.select(".tick:last-of-type text").clone()
      .attr("y", -3)
      .attr("dy", null)
      .attr("font-weight", "bold")
      .text("Idle (min.)"));

svg.append("g")
  .attr("transform", `translate(${marginLeft},0)`)
  .call(d3.axisLeft(y).tickSizeOuter(0))
  .call((g) => g.select(".domain").remove())
  .call((g) => g.select(".tick:last-of-type text").clone()
      .attr("x", 3)
      .attr("text-anchor", "start")
      .attr("font-weight", "bold")
      .text("Erupting (min.)"));

// Append the contours.
svg.append("g")
    .attr("fill", "none")
    .attr("stroke", "steelblue")
    .attr("stroke-linejoin", "round")
  .selectAll()
  .data(contours)
  .join("path")
    .attr("stroke-width", (d, i) => i % 5 ? 0.25 : 1)
    .attr("d", d3.geoPath());

// Append dots.
svg.append("g")
    .attr("stroke", "white")
  .selectAll()
  .data(faithful)
  .join("circle")
    .attr("cx", (d) => x(d.waiting))
    .attr("cy", (d) => y(d.eruptions))
    .attr("r", 2);

display(svg.node());
const faithful = FileAttachment("data/faithful.tsv").tsv({typed: true}).then(display);
✎ Suggest changes to this page