Public
Edited
Dec 12, 2023
Insert cell
md`# CS448b Visualization #3 scatterplot`
Insert cell
flights = fetch("https://raw.githubusercontent.com/e9d8v/cs448b/main/flights.csv")
.then(response => response.text())
.then(text => d3.csvParse(text));
Insert cell
jan_flights = flights.filter(flight => flight.MONTH === "1");
Insert cell
render_data_table(jan_flights.slice(-11, -1))
Insert cell
chart_data = jan_flights.map(d => {
let label = "No delay reason"; // default label
if (d["AIR_SYSTEM_DELAY"] === "1") {
label = "Air System Delay";
} else if (d["SECURITY_DELAY"] === "1") {
label = "Security Delay";
} else if (d["AIRLINE_DELAY"] === "1") {
label = "Airline Delay";
} else if (d["LATE_AIRCRAFT_DELAY"] === "1") {
label = "Late aircraft delay";
} else if (d["WEATHER_DELAY"] === "1") {
label = "Weather delay";
}
return {
x: +d["AIR_TIME"],
y: +d["DEPARTURE_DELAY"],
label: label,
originAirport: d["ORIGIN_AIRPORT"],
destinationAirport: d["DESTINATION_AIRPORT"],
airline: d["AIRLINE"]
};
}).filter(d => d.label !== "No delay reason");
Insert cell
delayTypes = [...d3.group(chart_data, d => d.label).keys()];
Insert cell
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

svg.append("g").call(xAxis);
svg.append("g").call(yAxis);

svg.node().update = currLabel => {
const labeled = currLabel ? chart_data.filter(d => d.label == currLabel) : chart_data;
const circles = svg
.selectAll("circle")
.data(labeled, (d, i) => i) // Ensure each data point has a unique id
.join(enter =>
enter
.append("circle")
.attr("cx", d => x(d.x)) // x(d.x) should correspond to air time
.attr("cy", y.range()[0])
)
.transition()
.delay(d => x(d.x))
.attr("cx", d => x(d.x))
.attr("cy", d => y(d.y)) // y(d.y) should correspond to departure delay
.attr("r", 2)
.style("fill", d => {
// Update this to reflect your color coding for delay types
switch (d.label) {
case "Air System Delay": return "blue";
case "Security Delay": return "orange";
case "Airline Delay": return "purple";
case "Late aircraft delay": return "red";
case "Weather delay": return "green";
case "No delay reason": return "gray";
default: return "gray";
}
})
.style("opacity", 0.5);
};

// Update axis titles
svg.append("text")
.attr("transform", `translate(${margin.left + (x.range()[1] - x.range()[0]) / 2}, ${height - 6})`)
.style("text-anchor", "middle")
.text("Air Time");

svg.append("text")
.attr("transform", `translate(${margin.left}, ${margin.top - 10})`)
.style("text-anchor", "middle")
.text("Departure Delay");

svg.node().update(''); // Call this to show all data initially
return svg.node();
}

Insert cell
tooltip = {
const div = d3.create("div")
.style("opacity", 0)
.style("position", "absolute")
.style("text-align", "left")
.style("width", "120px")
.style("height", "auto")
.style("padding", "2px")
.style("font", "12px sans-serif")
.style("background", "white")
.style("border", "0px")
.style("border-radius", "8px")
.style("pointer-events", "none");

return div.node();
}
Insert cell
chart.update(delayTypeSelect)
Insert cell
y_domain = d3.extent(chart_data, d => d.y)
Insert cell
x_domain = d3.extent(chart_data, d => d.x)
Insert cell
x = d3
.scaleLinear()
.domain(x_domain)
.range([margin.left, width - margin.right])
Insert cell
y = d3
.scaleLinear()
.domain(y_domain)
.range([height - margin.bottom, margin.top])
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x))
Insert cell
yAxis = g =>
g.attr("transform", `translate(${margin.left},0)`).call(d3.axisLeft(y))
Insert cell
md`## Appendix`
Insert cell
d3 = require("d3")
Insert cell
import { aq, op } from "@uwdata/arquero"
Insert cell
import { legend } from "@d3/color-legend"
Insert cell
topojson = require("topojson-client@3")
Insert cell
import { ramp } from "@d3/sequential-scales"
Insert cell
import {
displayCaution,
render_data_table,
table_styles
} from "@uw-info474/utilities"
Insert cell
margin = ({ top: 20, right: 30, bottom: 40, left: 100 })
Insert cell
height = 600
Insert cell
import { autoSelect } from "@jashkenas/inputs"
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