This is an extremely large dataset with over 650,000 entries logging bus breakdowns and delays for New York City schools. I want to organize the data in ways that can help me determine the route difficulty of these NYC school buses. Upon first looking at this data, I am interested in what years have the most breakdowns and delays, which routes have the most breakdowns and delays, and the biggest cause of breakdown or delays on these routes. I’m considering exploring which boros are most impacted as well, and what the length of delays tend to be, but I will have a clearer idea of how I want to analyze the data once I begin to clean the dataset.
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.4.4 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
data <- read.csv("Bus_Breakdown_and_Delays_20240225.csv")
a <- data %>%
select(School_Year, Route_Number, Busbreakdown_ID, Reason, Boro, Bus_Company_Name, How_Long_Delayed, Breakdown_or_Running_Late)
b <- a %>%
filter(Route_Number != "") %>%
# filter(Reason == "Heavy Traffic") %>%
filter(School_Year == "2017-2018") %>%
group_by(Reason) %>%
summarise(count = n())
c <- a %>%
select(School_Year, Reason)
table(c)
## Reason
## School_Year Accident Delayed by School Flat Tire Heavy Traffic
## 2015-2016 0 626 617 1709 35343
## 2016-2017 0 725 824 2817 51255
## 2017-2018 2 782 591 2770 55898
## 2018-2019 0 916 496 2592 72288
## 2019-2020 0 643 335 1534 43491
## 2020-2021 0 289 105 538 12744
## 2021-2022 0 674 704 1041 39531
## 2022-2023 0 599 483 1317 61712
## 2023-2024 0 349 187 806 31435
## Reason
## School_Year Late return from Field Trip Mechanical Problem Other Problem Run
## 2015-2016 1742 5516 11127 1030
## 2016-2017 1712 8231 10190 1154
## 2017-2018 1707 10193 11429 708
## 2018-2019 1739 10523 13585 2128
## 2019-2020 806 6467 8649 1604
## 2020-2021 9 2493 3179 47
## 2021-2022 278 5570 14792 5391
## 2022-2023 981 6909 19107 1354
## 2023-2024 419 4493 8992 6315
## Reason
## School_Year Weather Conditions Won`t Start
## 2015-2016 2529 2945
## 2016-2017 1995 4238
## 2017-2018 1612 3743
## 2018-2019 1366 3426
## 2019-2020 764 1705
## 2020-2021 421 613
## 2021-2022 1197 1001
## 2022-2023 1140 1049
## 2023-2024 1927 874
Because I am working with such a large dataset, I wanted to focus on a single year and look at that data more closely. I decided to organize my data so I would be able to determine which year had the most delays and breakdowns. Grouping by year and getting the count of entries per year allowed me to see which year had the most number of break downs and delays documented.
summary <- a %>%
group_by(School_Year) %>%
summarise(count = n())
Once I determined 2018 had the most delays and breakdowns in my dataset, I wanted to see which route number had the most entries. Filtering by school year and grouping by route number, I was able to get the counts for each route. Because there were over 6000 bus routes, I wanted to focus on the 10 routes with the highest number of delays and breakdowns so I would be able to create clearer visualizations for that data.
Year_2018_2019 <- a %>%
filter(School_Year == "2018-2019") %>%
group_by(Route_Number) %>%
summarise(count = n()) %>%
arrange(.,count) %>%
tail(10)
d <- a %>%
filter(Route_Number != "") %>%
group_by(Reason, School_Year) %>%
summarise(count = n())
## `summarise()` has grouped output by 'Reason'. You can override using the
## `.groups` argument.
ggplot(data = Year_2018_2019, aes(x = Route_Number, y = count)) +
geom_bar(position = "dodge", stat = "identity")
I wanted to look at what the biggest cause for delays in 2018 and compare that to the cause of delays over all of the years documented in this dataset.
ggplot(data = b, aes(x = count, y = Reason)) +
geom_bar(position = "dodge", stat = "identity")
ggplot(data = d, aes(x = count, y = Reason)) +
geom_bar(position = "dodge", stat = "identity")
Finally, I decided to look at which years had the most documented incidents.
ggplot(data = summary, aes(x = School_Year, y = count)) +
geom_bar(position = "dodge", stat = "identity")
There is more that can be done with this data set, but with the variables I chose to analyze, I was able to determine which year had the highest number of incidents (2018), which 10 bus routes within that year were most impacted (1, 2, 3, 5, M326, M817, M922, M965, M978, and M984), and what was the highest cause for delay reported (heavy traffic). If I wanted to delve deeper into the data I chose to analyze, I could look at the specific route each route number takes to see what parts of the city they run through. If heavy traffic is the main cause of bus delays as this data shows, it’s likely these routes run through areas of the city that are more densely populated or have higher rates of commuters in general. It could be interesting to see this data to be able confirm this, or see what other causes impacts these traffic on these specific routes. Additionally, looking at the reported incidents by year, I see that 2020-2021 had by far the lowest reported incidents. Knowing that this was the year of the start of the pandemic and many schools shifted to remote learning at that time, this dip in incidents makes a lot of sense, and as the 2024 school year has not yet ended, the lower count of reported incidents will likely change.
I would be interested to look at population data throughout 2015 - 2019 to see if there was an increase in NYC population to cause the steady increase of incidents over that time (given that heavy traffic is the main cause of incidents). It could also be helpful to look at commuter data to see if there is a trend of more drivers vs public transition commuters. The dip in incidents between 2019 and 2022 makes sense to me because of the pandemic, but I would be curious to know the reasoning for the trends in the data otherwise.