library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.3 ✔ readr 2.1.4
## ✔ forcats 1.0.0 ✔ stringr 1.5.0
## ✔ ggplot2 3.4.3 ✔ tibble 3.2.1
## ✔ lubridate 1.9.2 ✔ tidyr 1.3.0
## ✔ 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
library(plotly)
##
## Attaching package: 'plotly'
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following object is masked from 'package:graphics':
##
## layout
library(dplyr)
library(ggplot2)
library(ggmap)
## ℹ Google's Terms of Service: <https://mapsplatform.google.com>
## Stadia Maps' Terms of Service: <https://stadiamaps.com/terms-of-service/>
## OpenStreetMap's Tile Usage Policy: <https://operations.osmfoundation.org/policies/tiles/>
## ℹ Please cite ggmap if you use it! Use `citation("ggmap")` for details.
##
## Attaching package: 'ggmap'
##
##
## The following object is masked from 'package:plotly':
##
## wind
library(highcharter)
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
## Highcharts (www.highcharts.com) is a Highsoft software product which is
## not free for commercial and Governmental use
library(stringr)
library(datasets)
library(ggfortify)
library(htmltools)
library(GGally)
## Registered S3 method overwritten by 'GGally':
## method from
## +.gg ggplot2
library(leaflet)
library(DataExplorer)
setwd("/Users/nnokigbo/Downloads")
crashes <- read_csv("crashes.csv", locale = locale(encoding = "Latin1"))
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 172105 Columns: 43
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (38): Report Number, Agency Name, ACRS Report Type, Crash Date/Time, Rou...
## dbl (5): Local Case Number, Speed Limit, Vehicle Year, Latitude, Longitude
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
head(crashes)
## # A tibble: 6 × 43
## `Report Number` `Local Case Number` `Agency Name` `ACRS Report Type`
## <chr> <dbl> <chr> <chr>
## 1 MCP3040003N 190026050 Montgomery County Poli… Property Damage C…
## 2 EJ78850038 230034791 Gaithersburg Police De… Property Damage C…
## 3 MCP2009002G 230034583 Montgomery County Poli… Property Damage C…
## 4 MCP3201004C 230035036 Montgomery County Poli… Property Damage C…
## 5 MCP23290028 230035152 Montgomery County Poli… Property Damage C…
## 6 MCP295200DV 230032956 Montgomery County Poli… Property Damage C…
## # ℹ 39 more variables: `Crash Date/Time` <chr>, `Route Type` <chr>,
## # `Road Name` <chr>, `Cross-Street Type` <chr>, `Cross-Street Name` <chr>,
## # `Off-Road Description` <chr>, Municipality <chr>,
## # `Related Non-Motorist` <chr>, `Collision Type` <chr>, Weather <chr>,
## # `Surface Condition` <chr>, Light <chr>, `Traffic Control` <chr>,
## # `Driver Substance Abuse` <chr>, `Non-Motorist Substance Abuse` <chr>,
## # `Person ID` <chr>, `Driver At Fault` <chr>, `Injury Severity` <chr>, …
So off first glance, I notice that some things are not in the format I want them to be so let’s clean some of the data.
First I will replace the spaces in column names to underscores to make them easier to work with.
colnames(crashes) <- gsub(" ", "_", colnames(crashes))
Next I will get rid of columns that have too many NA’s to be useful. I will also get rid of columns that will not benefit me.
drop = c("Circumstance", "Off-Road_Description", "Related_Non-Motorist", "Non-Motorist_Substance_Abuse", "Report_Number", "Local_Case_Number", "Person_ID", "Vehicle_ID", "Vehicle_First_Impact_Location", "Vehicle_Second_Impact_Location")
crashes = crashes[,!(names(crashes) %in% drop)]
colnames(crashes)
## [1] "Agency_Name" "ACRS_Report_Type" "Crash_Date/Time"
## [4] "Route_Type" "Road_Name" "Cross-Street_Type"
## [7] "Cross-Street_Name" "Municipality" "Collision_Type"
## [10] "Weather" "Surface_Condition" "Light"
## [13] "Traffic_Control" "Driver_Substance_Abuse" "Driver_At_Fault"
## [16] "Injury_Severity" "Driver_Distracted_By" "Drivers_License_State"
## [19] "Vehicle_Damage_Extent" "Vehicle_Body_Type" "Vehicle_Movement"
## [22] "Vehicle_Continuing_Dir" "Vehicle_Going_Dir" "Speed_Limit"
## [25] "Driverless_Vehicle" "Parked_Vehicle" "Vehicle_Year"
## [28] "Vehicle_Make" "Vehicle_Model" "Equipment_Problems"
## [31] "Latitude" "Longitude" "Location"
What are drivers most distracted by?
Which vehicle make has experienced the most crashes in this data set?
Which vehicle make produces the highest average speed limit on the road.
How is the location of the crashes mapped out?
I am curious what distractions truly cause cars to crash.
crashes |>
group_by(Driver_Distracted_By) |>
count(Driver_Distracted_By) |>
arrange(desc(n))
## # A tibble: 19 × 2
## # Groups: Driver_Distracted_By [19]
## Driver_Distracted_By n
## <chr> <int>
## 1 NOT DISTRACTED 106709
## 2 UNKNOWN 32804
## 3 LOOKED BUT DID NOT SEE 21544
## 4 INATTENTIVE OR LOST IN THOUGHT 4319
## 5 OTHER DISTRACTION 3245
## 6 DISTRACTED BY OUTSIDE PERSON OBJECT OR EVENT 970
## 7 BY OTHER OCCUPANTS 418
## 8 OTHER CELLULAR PHONE RELATED 372
## 9 OTHER ELECTRONIC DEVICE (NAVIGATIONAL PALM PILOT) 325
## 10 TALKING OR LISTENING TO CELLULAR PHONE 282
## 11 NO DRIVER PRESENT 280
## 12 BY MOVING OBJECT IN VEHICLE 212
## 13 EATING OR DRINKING 196
## 14 ADJUSTING AUDIO AND OR CLIMATE CONTROLS 134
## 15 USING OTHER DEVICE CONTROLS INTEGRAL TO VEHICLE 92
## 16 TEXTING FROM A CELLULAR PHONE 66
## 17 USING DEVICE OBJECT BROUGHT INTO VEHICLE 63
## 18 DIALING CELLULAR PHONE 48
## 19 SMOKING RELATED 26
This is interesting. The most prevalent category is “Not Distracted”. This could be inaccurate because people are more like to lie when it could save them from being in trouble. However, for this data set, I want to look at the ones that were actually distracted and I want to take out the ones that don’t have many instances.
crashes |>
group_by(Driver_Distracted_By) |>
count(Driver_Distracted_By) |>
arrange(desc(n)) |>
filter(n > 250) |>
filter(!Driver_Distracted_By == "NOT DISTRACTED") |>
filter(!Driver_Distracted_By == "UNKNOWN") |>
filter(!Driver_Distracted_By == "BY MOVING OJECT IN VEHICLE") |>
filter(!Driver_Distracted_By == "EATING OR DRINKING") |>
filter(!Driver_Distracted_By == "ADJUSTING AUDIO AND OR CLIMATE CONTROLS") |>
filter(!Driver_Distracted_By == "USING OTHER DEVICE CONTROLS INTEGRAL TO VEHICLE") |>
filter(!Driver_Distracted_By == "TEXTING FROM A CELLULAR PHONE") |>
filter(!Driver_Distracted_By == "USING DEVICE OBJECT BROUGHT INTO VEHICLE") |>
filter(!Driver_Distracted_By == "DIALING CELLULAR PHONE") |>
filter(!Driver_Distracted_By == "SMOKING RELATED")
## # A tibble: 9 × 2
## # Groups: Driver_Distracted_By [9]
## Driver_Distracted_By n
## <chr> <int>
## 1 LOOKED BUT DID NOT SEE 21544
## 2 INATTENTIVE OR LOST IN THOUGHT 4319
## 3 OTHER DISTRACTION 3245
## 4 DISTRACTED BY OUTSIDE PERSON OBJECT OR EVENT 970
## 5 BY OTHER OCCUPANTS 418
## 6 OTHER CELLULAR PHONE RELATED 372
## 7 OTHER ELECTRONIC DEVICE (NAVIGATIONAL PALM PILOT) 325
## 8 TALKING OR LISTENING TO CELLULAR PHONE 282
## 9 NO DRIVER PRESENT 280
crashes_bar <- crashes |>
filter(!Driver_Distracted_By == "NOT DISTRACTED") |>
filter(!Driver_Distracted_By == "UNKNOWN")|>
filter(!Driver_Distracted_By == "BY MOVING OJECT IN VEHICLE") |>
filter(!Driver_Distracted_By == "EATING OR DRINKING") |>
filter(!Driver_Distracted_By == "ADJUSTING AUDIO AND OR CLIMATE CONTROLS") |>
filter(!Driver_Distracted_By == "USING OTHER DEVICE CONTROLS INTEGRAL TO VEHICLE") |>
filter(!Driver_Distracted_By == "TEXTING FROM A CELLULAR PHONE") |>
filter(!Driver_Distracted_By == "USING DEVICE OBJECT BROUGHT INTO VEHICLE") |>
filter(!Driver_Distracted_By == "DIALING CELLULAR PHONE") |>
filter(!Driver_Distracted_By == "SMOKING RELATED")
ggplot(crashes_bar, aes(y = Driver_Distracted_By)) +
geom_bar() +
labs(
x = "Counts",
y = "Distraction"
)
So I want to know which vehicle make produces the most amount of crashes in this data set. First, the Vehicle Make column is a bit dirty so I want to create a more tidy set of groups for them.
crashesmod <- crashes |>
relocate(Vehicle_Make) |>
mutate(Vehicle_Make = case_when((grepl("TOY", crashes$Vehicle_Make) == TRUE) ~ "Toyota",
(grepl("NISS", crashes$Vehicle_Make) == TRUE) ~ "Nissan",
(grepl("UNKN", crashes$Vehicle_Make) == TRUE) ~ "Unknown",
(grepl("SUB", crashes$Vehicle_Make) == TRUE) ~ "Subaru",
(grepl("VOLK", crashes$Vehicle_Make) == TRUE) ~ "Volkswagon",
(grepl("YAM", crashes$Vehicle_Make) == TRUE) ~ "Yamaha",
(grepl("CHR", crashes$Vehicle_Make) == TRUE) ~ "Chrysler",
(grepl("GIL", crashes$Vehicle_Make) == TRUE) ~ "Gill",
(grepl("HON", crashes$Vehicle_Make) == TRUE) ~ "Honda",
(grepl("LEX", crashes$Vehicle_Make) == TRUE) ~ "Lexus",
(grepl("CHEV", crashes$Vehicle_Make) == TRUE) ~ "Chevrolet",
(grepl("FORD", crashes$Vehicle_Make) == TRUE) ~ "Ford",
(grepl("FREI", crashes$Vehicle_Make) == TRUE) ~ "Freight",
(grepl("HYUN", crashes$Vehicle_Make) == TRUE) ~ "Hyundai",
(grepl("MAZ", crashes$Vehicle_Make) == TRUE) ~ "Mazda",
(grepl("HARL", crashes$Vehicle_Make) == TRUE) ~ "Harley Davidson",
(grepl("DODG", crashes$Vehicle_Make) == TRUE) ~ "Dodge",
(grepl("RAM", crashes$Vehicle_Make) == TRUE) ~ "Ram",
(grepl("INFI", crashes$Vehicle_Make) == TRUE) ~ "Infinity",
(grepl("ACUR", crashes$Vehicle_Make) == TRUE) ~ "Acura",
(grepl("MER", crashes$Vehicle_Make) == TRUE) ~ "Mercedez",
(grepl("BM", crashes$Vehicle_Make) == TRUE) ~ "BMW",
(grepl("GM", crashes$Vehicle_Make) == TRUE) ~ "GMC",
(grepl("VOLVO", crashes$Vehicle_Make) == TRUE) ~ "Volvo",
(grepl("TESLA", crashes$Vehicle_Make) == TRUE) ~ "Tesla",
(grepl("AUD", crashes$Vehicle_Make) == TRUE) ~ "Audi",
(grepl("CORV", crashes$Vehicle_Make) == TRUE) ~ "Corvette",
(grepl("CAD", crashes$Vehicle_Make) == TRUE) ~ "Cadillac",
(grepl("JAG", crashes$Vehicle_Make) == TRUE) ~ "Jaguar",
(grepl("PETER", crashes$Vehicle_Make) == TRUE) ~ "Peterbuilt",
(grepl("JEEP", crashes$Vehicle_Make) == TRUE) ~ "Jeep",
(grepl("KEN", crashes$Vehicle_Make) == TRUE) ~ "Kenworth",
(grepl("HINO", crashes$Vehicle_Make) == TRUE) ~ "Hino",
(grepl("KIA", crashes$Vehicle_Make) == TRUE) ~ "Kia"))
unique(crashesmod$Vehicle_Make)
## [1] "Honda" "GMC" "Ford" "Kia"
## [5] "Toyota" "Gill" "Subaru" "BMW"
## [9] "Hyundai" "Volkswagon" "Dodge" "Nissan"
## [13] "Lexus" "Yamaha" "Unknown" "Infinity"
## [17] "Mazda" "Acura" "Freight" "Chevrolet"
## [21] "Harley Davidson" "Volvo" "Chrysler" "Mercedez"
## [25] "Peterbuilt" "Jaguar" "Kenworth" "Jeep"
## [29] "Hino" NA "Ram" "Cadillac"
## [33] "Tesla" "Audi" "Corvette"
Now that I’ve tidied the column, let’s see which
crashesmod |>
group_by(Vehicle_Make) |>
count(Vehicle_Make) |>
arrange(desc(n))|>
filter(!Vehicle_Make == "NA")
## # A tibble: 34 × 2
## # Groups: Vehicle_Make [34]
## Vehicle_Make n
## <chr> <int>
## 1 Toyota 32745
## 2 Honda 24676
## 3 Ford 17154
## 4 Nissan 11355
## 5 Chevrolet 10927
## 6 Hyundai 6294
## 7 Dodge 5365
## 8 Mercedez 4253
## 9 Subaru 3821
## 10 Lexus 3806
## # ℹ 24 more rows
To answer my question of which vehicle make has experienced the most crashes in this data set, the answer is Toyota. This is very interesting because Toyota are usually very reliable vehicle that last a long time. I doubt the answer is because of the make of the actual car. I believe this is the answer because a lot of people have Toyotas so it would make sense that they crash the most. I would like to have to data to see how this information owuld present if it were per-capita
Now that we have already cleaned the vehicle make column, let’s create a treemap to see the average speed limit on road of crash based on make.
speedlimitplot <- crashesmod |>
group_by(Vehicle_Make) |>
summarise(avg = mean(Speed_Limit, na.rm = TRUE)) |>
filter(!Vehicle_Make == "NA") |>
hchart(type = "treemap", hcaes(x = Vehicle_Make, value = avg, color = avg, colorByPoint = TRUE)) |>
hc_colorAxis(
maxColor = "#DB7CBD",
minColor = "#FFFFFF") |>
hc_add_theme(hc_theme_bloom()) |>
hc_title(text = "Average Speed Limit on Road of Crash based on Car Model") |>
hc_subtitle(text = "Shaded by Mean Speed Limit on Road of Crash") |>
hc_caption(text = "Source: Maryland Car Crashes Dataset")
speedlimitplot
It seems that the vehicle make with the highest average speed limit that the crash occured on is Harley Davidson. This information could be incorrect universally though. Most of the cars with high average speed limits are cars that are not very common. More common cars would have more accurate data because they have more data. This is a good thing to keep in mind.
popupcrashes <- paste0(
"<b>Date/Time: </b>", crashes$`Crash_Date/Time`, "<br>",
"<b>Type: </b>", crashes$ACRS_Report_Type, "<br>",
"<b>Conditions: </b>", crashes$Surface_Condition, "<br>",
"<b>Type: </b>", crashes$Road_Name, "<br>"
)
leaflet() |>
setView(lng = -76.951315, lat = 39.0838, zoom = 13) |>
addProviderTiles("Esri.WorldStreetMap") |>
addCircles(
data = crashes,
radius = 25,
color = "#715145",
fillOpacity = 1,
popup = popupcrashes
)
## Assuming "Longitude" and "Latitude" are longitude and latitude, respectively