Public
Edited
Feb 15, 2024
Fork of Homework 1
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
img_9789 = FileAttachment("IMG_9789.jpg").image()
Insert cell
Insert cell
Insert cell
Insert cell
FHV_data = {
const scsv = d3.dsvFormat(",") // Important to define the separator of your CSV file
return scsv.parse(await FileAttachment("FHV_Base_Aggregate_Report_20240205.csv").text())
}
Insert cell
Insert cell
top5_companies = d3.groupSort(
// our data
FHV_data,
// we want to sort the groups by their median rating
group => d3.sum(group, d => d["Total Dispatched Trips"]),
// we want to group the cereals by brand
d => d["Base Name"]
).reverse().slice(0,5)
Insert cell
Insert cell
Insert cell
top5_company_dispatches = FHV_data
.filter(d => new Set(top5_companies).has(d["Base Name"]))
//.map(d => d["Year"])
.map(currentElement => ({
"Base License Number": currentElement["Base License Number"],
"Base Name": currentElement["Base Name"],
"DBA": currentElement["DBA"],
"Year": currentElement["Year"],
"Month": currentElement["Month"],
"Month Name": currentElement["Month Name"],
"Total Dispatched Trips": parseInt(currentElement["Total Dispatched Trips"]),
"Total Dispatched Shared Trips": currentElement["Total Dispatched Shared Trips"],
"Unique Dispatched Vehicles": parseInt(currentElement["Unique Dispatched Vehicles"]),
"timestamp": new Date(currentElement["Year"], currentElement["Month"]-1)
})).sort((a, b) => d3.ascending(a.timestamp, b.timestamp))
Insert cell
Insert cell
margin = ({top: 30, bottom: 50, left: 60, right: 150})
Insert cell
visWidth = 1152
Insert cell
visHeight = 500
Insert cell
Insert cell
//TO DO Scale 1
dateExtent = d3.extent(top5_company_dispatches, d => d.timestamp)
Insert cell
x = d3.scaleTime()
.domain(dateExtent)
.range([margin.left, width - margin.right])
Insert cell
maxTrips = d3.max(top5_company_dispatches, d => d["Total Dispatched Trips"])
Insert cell
y = d3.scaleLinear()
.domain([0, maxTrips]).nice()
.range([visHeight - margin.bottom, margin.top]);
Insert cell
colors = d3.scaleOrdinal(top5_companies,d3.schemeCategory10)
Insert cell
line = d3.line()
.x(d => x(d.timestamp))
.y(d => y(d["Total Dispatched Trips"]))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
img_97901 = FileAttachment("IMG_9790@1.jpg").image()
Insert cell
Insert cell
Insert cell
margin2 = ({top: 20, bottom: 40, left: 80, right: 75})//TO DO
Insert cell
width2 = 600
Insert cell
height2 = 500
Insert cell
margin3 = ({top: 30, bottom: 50, left: 60, right: 150})//TO DO
Insert cell
width3 = 600
Insert cell
height3 = 500
Insert cell
Insert cell
// Scale 1: total dispatched trips
dispatched_trips = d3.scaleLinear()
.domain([0, maxTrips]).nice()
.range([height2 - margin2.bottom, margin2.top]);
Insert cell
maxVehicles = d3.max(top5_company_dispatches, d => d["Unique Dispatched Vehicles"])
Insert cell
// Scale 2: unique vehicles dispatched

unique_cars = d3.scaleLinear()
.domain([0, maxVehicles]).nice()
.range([height3 - margin3.bottom, margin3.top]);
Insert cell
// Scale 3: timestamp
time_scale = d3.scaleTime()
.domain(dateExtent)
.range([margin2.left, width2 - margin2.right])
Insert cell
// Scale 4: colors
colorCompany = d3.scaleOrdinal(top5_companies,d3.schemeCategory10);
Insert cell
Insert cell
Insert cell
Insert cell
function leftVisualization() {

// the value for when there is no brush
const initialValue = top5_company_dispatches;//TO DO

//create SVG, add any axes, draw any marks, etc
// set up

const svg = d3.create('svg')
.attr('width', width2 + margin2.left + margin2.right)
.attr('height', height2 + margin2.top + margin2.bottom)
.property('value', initialValue);
// add title
svg.append("text")
.attr("x", width2 / 2)
.attr("y", 0)
.attr("text-anchor", "middle")
.attr("dominant-baseline", "hanging")
.attr("font-family", "sans-serif")
.attr("font-size", "16px")
.text("# Dispatched Trips over Time");
// axes
const xAxis = d3.axisBottom(time_scale);
const yAxis = d3.axisLeft(dispatched_trips);
svg.append("g")
.call(xAxis)
.attr("transform", `translate(0, ${height2-20})`)
.append("text")
.attr("x", width2 / 2)
.attr("y", 40)
.attr("fill", "black")
.attr("text-anchor", "middle")
.text("Year");
svg.append("g")
.call(yAxis)
.attr("transform", `translate(${margin2.left-10},0)`)
.append("text")
.attr("x", -20)
.attr("y", 10)
.attr("fill", "black")
.attr("text-anchor", "middle")
.text("# Dispatched Trips");
// draw points
const radius = 3;
const dots = svg.selectAll('circle')
.data(top5_company_dispatches)
.join('circle')
.attr('cx', d => time_scale(d["timestamp"]))
.attr('cy', d => dispatched_trips(d["Total Dispatched Trips"]))
.attr('fill', d => colors(d["Base Name"]))
.attr('opacity', 1)
.attr('r', radius);
//create brush
const brush = d3.brush()
// set the space that the brush can take up
.extent([[margin2.left, margin2.top], [width2, height2]])
// handle events
.on('brush', onBrush)
.on('end', onEnd);
svg.append('g')
.call(brush);
//handle brush events
function onBrush(event) {
// event.selection gives us the coordinates of the
// top left and bottom right of the brush box
const [[x1, y1], [x2, y2]] = event.selection;
// return true if the dot is in the brush box, false otherwise
function isBrushed(d) {
const cx = time_scale(d["timestamp"]);
const cy = dispatched_trips(d["Total Dispatched Trips"])
return cx >= x1 && cx <= x2 && cy >= y1 && cy <= y2;
}
dots.attr('fill', d => isBrushed(d) ? colors(d["Base Name"]):'gray');
svg.property('value', dispatched_trips.filter(isBrushed)).dispatch('input');
}
function onEnd(event) {
// if the brush is cleared
if (event.selection === null) {
// reset the color of all of the dots
dots.attr('fill', d => colors(d["Base Name"]))
svg.property('value', initialValue).dispatch('input');
}
}
return svg.node();
}
Insert cell
Insert cell
function rightVisualization() {
//create SVG, add any axes, draw any marks, etc for initial view
const svg = d3.create('svg')
.attr('width', width2 + margin2.left + margin2.right)
.attr('height', height2 + margin2.top + margin2.bottom);
// add title
svg.append("text")
.attr("x", width2 / 2)
.attr("y", 0)
.attr("text-anchor", "middle")
.attr("dominant-baseline", "hanging")
.attr("font-family", "sans-serif")
.attr("font-size", "16px")
.text("# Unique Vehicles over Time");
// axes
const xAxis = d3.axisBottom(time_scale);
const yAxis = d3.axisLeft(unique_cars);
svg.append("g")
.call(xAxis)
.attr("transform", `translate(0, ${height2-20})`)
.append("text")
.attr("x", width2 / 2)
.attr("y", 40)
.attr("fill", "black")
.attr("text-anchor", "middle")
.text("Year");
svg.append("g")
.call(yAxis)
.attr("transform", `translate(${margin2.left-10},0)`)
.append("text")
.attr("x", -20)
.attr("y", 10)
.attr("fill", "black")
.attr("text-anchor", "middle")
.text("# Unique Vehicles");
// draw points
const radius = 3;
const dots = svg.selectAll('circle')
.data(top5_company_dispatches)
.join('circle')
.attr('cx', d => time_scale(d["timestamp"]))
.attr('cy', d => unique_cars(d["Unique Dispatched Vehicles"]))
.attr('fill', d => colors(d["Base Name"]))
.attr('opacity', 1)
.attr('r', radius);
//update view based on leftVisualization selection
function update(data) {
}

return Object.assign(svg.node(), { update });;
}
Insert cell
Insert cell
{
const vis_left = leftVisualization();
const vis_right = rightVisualization();

// update the visualization on the right when the visualization on the left
// selection changes
d3.select(vis_left).on('input', () => {
vis_right.update(vis_left.value);
});

// intial state of visualization on the right
vis_right.update(vis_left.value);

// use HTML to place the two charts next to each other
return html`<div style="display: flex">${vis_left}${vis_right}</div>`;
}
Insert cell
Insert cell
Insert cell
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