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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more