diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore index 0d595d6..5127f26 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ -.venv -.DS_Store -.ipynb_checkpoints/ +boston_311_2023_raw.csv diff --git a/answers/311_boston_data.csv b/311_boston_data.csv similarity index 100% rename from answers/311_boston_data.csv rename to 311_boston_data.csv diff --git a/Setup.md b/Setup.md index cdc3a26..1c4a5d1 100644 --- a/Setup.md +++ b/Setup.md @@ -44,6 +44,7 @@ error: externally-managed-environment 5. **Install your package:** ```bash + python3 -m http.server pip3 install pandas ``` diff --git a/answers/.DS_Store b/answers/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/answers/.DS_Store differ diff --git a/answers/index.html b/answers/index.html deleted file mode 100644 index 86ec8d7..0000000 --- a/answers/index.html +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - D3 Bar Chart - 311 Calls in Boston - - - -
-

311 Calls in Boston in 2023

-

Broken down by the top 10 types

-
-
- - - - - diff --git a/answers/script.js b/answers/script.js deleted file mode 100644 index e8770a3..0000000 --- a/answers/script.js +++ /dev/null @@ -1,70 +0,0 @@ -// Load CSV data -d3.csv('311_boston_data.csv').then(data => { - // Process the data - data.forEach(d => { - d.Count = +d.Count; // Convert Count to a number - }); - - // Sort the data by Count in descending order. first step to top 10 - data.sort((a, b) => b.Count - a.Count); - - // Take only the top 10 types - const top10Data = data.slice(0, 10); - - // Set up SVG container - const svgWidth = 800; - const svgHeight = 500; - const margin = { top: 40, right: 40, bottom: 80, left: 200 }; - const width = svgWidth - margin.left - margin.right; - const height = svgHeight - margin.top - margin.bottom; - - const svg = d3.select('#chart_311') - .append('svg') - .attr('width', svgWidth) - .attr('height', svgHeight) - .append('g') - .attr('transform', `translate(${margin.left},${margin.top})`); - - // Create scales - const yScale = d3.scaleBand() - .domain(top10Data.map(d => d.reason)) - .range([0, height]) - .padding(0.2); - - const xScale = d3.scaleLinear() - .domain([0, d3.max(top10Data, d => d.Count)]) - .range([0, width]); - - // Create bars - svg.selectAll('rect') - .data(top10Data) - .enter() - .append('rect') - .attr('x', 0) - .attr('y', d => yScale(d.reason)) - .attr('width', d => xScale(d.Count)) - .attr('height', yScale.bandwidth()) - .attr('fill', 'blue') - .on('mouseover', function (event, d) { - d3.select(this).attr('fill', 'orange'); // Change color on hover - }) - .on('mouseout', function () { - d3.select(this).attr('fill', 'blue'); // Revert color on mouseout - }); - - // Add axes - svg.append('g') - .call(d3.axisLeft(yScale)); - - svg.append('g') - .attr('transform', `translate(0,${height})`) - .call(d3.axisBottom(xScale)); - - // Add attribution line at the bottom - svg.append('text') - .attr('x', width / 2) - .attr('y', height + margin.top + 20) // Adjust the y-coordinate for proper placement - .attr('text-anchor', 'left') - .style('font-size', '12px') - .text('Chart created by Aarushi Sahejpal. Data source: Boston.gov'); -}); diff --git a/answers/styles.css b/answers/styles.css index c8f955d..a85f21e 100644 --- a/answers/styles.css +++ b/answers/styles.css @@ -1,5 +1,67 @@ /* Add any CSS styles here */ body { + body { + font-family: Arial, sans-serif; + margin: 20px; + background-color: #f9f9f9; + color: #333; +} + +header { + text-align: center; + margin-bottom: 20px; +} + +#chart { + width: 80%; + margin: 0 auto; +} + +button { + display: block; + margin: 20px auto; + padding: 10px 20px; + font-size: 16px; + cursor: pointer; +} + +footer { + text-align: center; + margin-top: 20px; + font-size: 14px; + color: #666; +} + body { + font-family: Arial, sans-serif; + margin: 20px; + background-color: #f9f9f9; + color: #333; +} + +header { + text-align: center; + margin-bottom: 20px; +} + +#chart { + width: 80%; + margin: 0 auto; +} + +button { + display: block; + margin: 20px auto; + padding: 10px 20px; + font-size: 16px; + cursor: pointer; +} + +footer { + text-align: center; + margin-top: 20px; + font-size: 14px; + color: #666; +} font-family: 'Roboto', sans-serif; /* Use Roboto font */ background-color: whitesmoke; color: black; diff --git a/boston_311_2023_by_reason.csv b/boston_311_2023_by_reason.csv new file mode 100644 index 0000000..076c2a2 --- /dev/null +++ b/boston_311_2023_by_reason.csv @@ -0,0 +1,45 @@ +reason,Count +Abandoned Bicycle,1318 +Administrative & General Requests,2025 +Air Pollution Control,35 +Alert Boston,3 +Animal Issues,4155 +Billing,6 +Boston Bikes,64 +Bridge Maintenance,8 +Building,5209 +Catchbasin,621 +Cemetery,29 +Code Enforcement,31812 +Employee & General Comments,2166 +Enforcement & Abandoned Vehicles,61541 +Environmental Services,4416 +Fire Hydrant,205 +General Request,196 +Generic Noise Disturbance,109 +Graffiti,1839 +Health,1349 +Highway Maintenance,25096 +Housing,7590 +MBTA,1 +Massport,8 +Needle Program,7413 +Neighborhood Services Issues,28 +Noise Disturbance,832 +Notification,607 +Office of The Parking Clerk,18 +Operations,283 +Park Maintenance & Safety,7932 +Parking Complaints,19 +Pothole,85 +Programs,6 +Recycling,9955 +Sanitation,59389 +Sidewalk Cover / Manhole,291 +Signs & Signals,11209 +Street Cleaning,45659 +Street Lights,8499 +Traffic Management & Engineering,751 +Trees,10390 +Valet,7 +Weights and Measures,52 diff --git a/index.html b/index.html index d80e631..c266f58 100644 --- a/index.html +++ b/index.html @@ -1 +1,26 @@ - \ No newline at end of file + + + + + + + 311 Calls Visualization + + + + +
+

Top 10 Reasons for 311 Calls in Boston

+

A look at the most common reasons for 311 calls in 2023

+
+
+
+ + +
+ + +s \ No newline at end of file diff --git a/script.js b/script.js new file mode 100644 index 0000000..3653eb5 --- /dev/null +++ b/script.js @@ -0,0 +1,84 @@ +// Load 311 calls data (replace '311_calls.csv' with the actual path to your dataset) +d3.csv("311_boston_data.csv").then(function(data) { + // Process data: Count the reasons and sort by frequency + let reasonCounts = d3.rollup( + data, + v => v.length, + d => d.reason + ); + + // Convert Map to Array and sort by counts + reasonCounts = Array.from(reasonCounts, ([reason, count]) => ({ reason, count })) + .sort((a, b) => d3.descending(a.count, b.count)); + + // Extract top 10 reasons + const top10 = reasonCounts.slice(0, 10); + + // Chart dimensions and margins + const margin = { top: 20, right: 20, bottom: 20, left: 250 }; + const width = 800 - margin.left - margin.right; + const height = 400 - margin.top - margin.bottom; + + // Create SVG canvas + const svg = d3.select("#chart") + .append("svg") + .attr("width", width + margin.left + margin.right) + .attr("height", height + margin.top + margin.bottom) + .append("g") + .attr("transform", `translate(${margin.left}, ${margin.top})`); + + // Create scales + const xScale = d3.scaleLinear() + .domain([0, d3.max(top10, d => d.count)]) + .range([0, width]); + + const yScale = d3.scaleBand() + .domain(top10.map(d => d.reason)) + .range([0, height]) + .padding(0.1); + + // Add bars + svg.selectAll(".bar") + .data(top10) + .enter() + .append("rect") + .attr("class", "bar") + .attr("y", d => yScale(d.reason)) + .attr("x", 0) + .attr("width", d => xScale(d.count)) + .attr("height", yScale.bandwidth()) + .style("fill", "#4CAF50"); + + // Add y-axis + svg.append("g") + .call(d3.axisLeft(yScale).tickSize(0)) + .selectAll("text") + .style("font-size", "12px"); + + // Add x-axis + svg.append("g") + .attr("transform", `translate(0, ${height})`) + .call(d3.axisBottom(xScale).ticks(5)) + .selectAll("text") + .style("font-size", "12px"); + + // Add headline + svg.append("text") + .attr("x", width / 2) + .attr("y", -10) + .attr("text-anchor", "middle") + .style("font-size", "18px") + .style("font-weight", "bold") + .text("Top 10 Reasons for 311 Calls in Boston (2023)"); + + // Add subheadline + svg.append("text") + .attr("x", width / 2) + .attr("y", 10) + .attr("text-anchor", "middle") + .style("font-size", "14px") + .text("Based on the most frequent complaints logged in 2023"); + + // Optional: Log for debugging + console.log("Top 10 reasons for 311 calls:", top10); +}); diff --git a/styles/styles.css b/styles/styles.css new file mode 100644 index 0000000..06b78f1 --- /dev/null +++ b/styles/styles.css @@ -0,0 +1,31 @@ +body { + font-family: Arial, sans-serif; + margin: 20px; + background-color: #f9f9f9; + color: #333; +} + +header { + text-align: center; + margin-bottom: 20px; +} + +#chart { + width: 80%; + margin: 0 auto; +} + +button { + display: block; + margin: 20px auto; + padding: 10px 20px; + font-size: 16px; + cursor: pointer; +} + +footer { + text-align: center; + margin-top: 20px; + font-size: 14px; + color: #666; +} \ No newline at end of file