Number of Crashes
Total Injuries
Total Fatalities
Rate of Harm
Number of Crashes
Total Injuries
Total Fatalities
Rate of Harm
| Year | Total Accidents | Fatal Accidents | Injurious Accidents | Harmless Accidents |
|---|---|---|---|---|
| Year | Total Accidents | Fatal Accidents | Injurious Accidents | Harmless Accidents |
| 2012 | 3701 | 2 | 1131 | 2568 |
| 2013 | 3807 | 7 | 1202 | 2598 |
| 2014 | 3827 | 12 | 1222 | 2593 |
| 2015 | 4053 | 5 | 1166 | 2882 |
| 2016 | 4262 | 11 | 1250 | 3001 |
| 2017 | 4401 | 10 | 1390 | 3001 |
| 2018 | 1242 | 1 | 407 | 834 |
| Year | Proportion Fatal (%) | Proportion Injurious (%) | Proportion Harmless (%) |
|---|---|---|---|
| Year | Proportion Fatal (%) | Proportion Injurious (%) | Proportion Harmless (%) |
| 2012 | 0.05 | 30.56 | 69.39 |
| 2013 | 0.18 | 31.57 | 68.24 |
| 2014 | 0.31 | 31.93 | 67.76 |
| 2015 | 0.12 | 28.77 | 71.11 |
| 2016 | 0.26 | 29.33 | 70.41 |
| 2017 | 0.23 | 31.58 | 68.19 |
| 2018 | 0.08 | 32.77 | 67.15 |
Tab Breakdown:
Day & Time: Use the map to visualize traffic accidents by the time of day and day of the week.
Age, Gender, & Method: This tab allows you to visually explore accidents based on the drivers characteristics, including age, gender, and type of transportation.
Comparisons: Create distinct maps for each driver to further isolate accidents using the variables of Age, Gender, & Method
Year & Harm: Compare rates of accidents across the years, including proportions of fatal, injurious, and harmless accidents.
Substance Use: View a map of accidents by the involvement of substances within common traffic periods.
DATA DICTIONARY
| column | description |
|---|---|
| Incidentid | Unique incident ID number assigned by Arizona Department of Transportation (ADOT). |
| DateTime | Date and time that the crash occurred. |
| Year | Year that the crash occurred. |
| StreetName | The street that the crash occurred on. |
| CrossStreet | The nearest intersecting street or road. |
| Distance | The distance, in feet, that the crash occurred from the cross-street. This distance is expressed in feet with positive numbers being either north or east of the intersection and negative numbers being either south or west of the intersection, based on the orientation of the street that the incident occurred on. (i.e. Baseline Rd runs in an East-West direction and so a negative number would be west of the intersection and a positive number would be east of the intersection). |
| JunctionRelation | The location of the crash in relation to a junction, either an intersection or connection between a driveway and a roadway. |
| Totalinjuries | Total number of persons with non-fatal injuries involved in the crash. |
| Totalfatalities | Total number of persons with fatal injuries involved in the crash. |
| Injuryseverity | The highest severity of injury of all persons involved in the crash. NO INJURY - No complaint or treatment was required by the person. POSSIBLE INJURY - Complaint of pain without visible injury. Includes momentary unconsciousness, claim of injuries not evident, limping, complaint of pain, nausea or hysteria. NON-INCAPACITATING INJURY - Any injury, other than a fatal injury or an incapacitating injury, which is evident to observers at the scene of the crash in which the injury occurred. Examples: contusions (bruises), laceration, bloody nose, lump on head, or abrasions. INCAPACITATING INJURY - Any injury, other than a fatal injury, which prevents the injured person from walking, driving or normally continuing the activities the person was capable of performing before the injury occurred. Often defined as needing help from the scene. Includes: severe lacerations, broken or distorted limbs, skull or chest injuries, abdominal injuries, unconsciousness when taken from the crash scene. FATAL INJURY - Any injury that results in death within 30 days after the crash occurred. |
| Collisionmanner | Identifies the manner in which two vehicles initially came into contact. |
| Lightcondition | The type/level of light that existed at the time of the crash. |
| Weather | The prevailing (most significant) atmospheric conditions that existed at the time of the crash. |
| SurfaceCondition | The roadway surface condition at the time and place of a crash. |
| Unittype_One | Driver, Passenger, Pedestrian, Pedalcyclist or Driverless. |
| Age_Drv1 | |
| Gender_Drv1 | |
| Traveldirection_One | The direction the unit was traveling before the incident occurred, |
| Unitaction_One | The maneuver, or last action, of the unit before the crash. |
| Violation1_Drv1 | The main violation/behavior of the unit that contributed to the crash. |
| AlcoholUse_Drv1 | Indicates whether alcohol was a contributing factor in the crash or not. |
| DrugUse_Drv1 | Indicates whether drug use was a contributing factor in the crash or not. |
| Unittype_Two | Driver, Passenger, Pedestrian, Pedalcyclist or Driverless. |
| Age_Drv2 | |
| Gender_Drv2 | |
| Traveldirection_Two | The direction the unit was traveling before the incident occurred. |
| Unitaction_Two | The maneuver, or last action, of the unit before the crash. |
| Violation1_Drv2 | The main violation/behavior of the unit that contributed to the crash. |
| AlcoholUse_Drv2 | Indicates whether alcohol was a contributing factor in the crash or not. |
| DrugUse_Drv2 | Indicates whether drug use was a contributing factor in the crash or not. |
| Latitude | Used to specify the precise location of the crash. |
| Longitude | Used to specify the precise location of the crash. |
---
title: "CPP 526: Final Project"
output:
flexdashboard::flex_dashboard:
theme: spacelab
source: embed
smart: false
runtime: shiny
---
```{r include = FALSE}
# LOAD PACKAGES
library( DT)
library( ggmap )
library( shiny )
library( knitr )
library( pander )
library( leaflet )
library( viridis )
library( rsconnect )
library( tidyverse )
library( flexdashboard )
library(ggplot2)
# READ IN DATA
url <- paste0("https://github.com/DS4PS/Data-",
"Science-Class/blob/master/DATA",
"/TempeTrafficAccidents.rds?raw=true")
dat <- readRDS( gzcon( url( url ) ) )
# DATA PREPROCESSING I: INJURIES & FATALITIES
dat <- na.omit(dat) # Remove NA
dat$fatal <- dat$Totalfatalities > 0 # 1+ fatalities
dat$inj <- dat$Totalinjuries > 0 & dat$Totalfatalities == 0 # 1+ injuries, 0 fatal
dat$nohurt <- dat$Totalfatalities + dat$Totalinjuries == 0 # Harmless
date.vec <- strptime(dat$DateTime, format = "%m/%d/%y %H:%M") # Datetime variables
dat$hour <- format(date.vec, format = "%H") %>% as.numeric()
dat$month <- format(date.vec, format = "%b")
dat$day <- format(date.vec, format = "%a")
dat$day365 <- format(date.vec, format = "%j")
dat$week <- format(date.vec, format = "%V")
# DATA PREPROCESSING II: NAMED INTERVALS OF TIME
dat <- dat %>%
mutate(time.of.day = case_when(hour >= 6 & hour <= 9 ~ "Morning Commute",
hour >= 16 & hour <= 19 ~ "Evening Commute",
hour >= 14 & hour <= 15 ~ "School Pickup",
hour >= 9 & hour <= 13 ~ "Work",
hour >= 20 & hour <= 23 ~ "Night",
hour <= 5 & hour >= 0 ~ "Midnight to Dawn"))
dat$harm <- ifelse(test = dat$Totalinjuries > 0 | dat$Totalfatalities > 0,
yes = "Harm",
no = "No Harm")
# DATA PREPROCESSING III: PERMUTATIONS OF INEBRIATION
dat <- dat %>%
mutate(d1.substance = case_when(AlcoholUse_Drv1 == "Alcohol" &
DrugUse_Drv1 == "No Apparent Influence" ~ "Alcohol",
AlcoholUse_Drv1 == "No Apparent Influence" &
DrugUse_Drv1 == "Drugs" ~ "Drugs",
AlcoholUse_Drv1 == "Alcohol" &
DrugUse_Drv1 == "Drugs" ~ "Alcohol and Drugs",
AlcoholUse_Drv1 == "No Apparent Influence" &
DrugUse_Drv1 == "No Apparent Influence" ~ "No Apparent Influence"))
dat <- dat %>%
mutate(d2.substance = case_when(AlcoholUse_Drv2 == "Alcohol" &
DrugUse_Drv2 == "No Apparent Influence" ~ "Alcohol",
AlcoholUse_Drv2 == "No Apparent Influence" &
DrugUse_Drv2 == "Drugs" ~ "Drugs",
AlcoholUse_Drv2 == "Alcohol" &
DrugUse_Drv2 == "Drugs" ~ "Alcohol and Drugs",
AlcoholUse_Drv2 == "No Apparent Influence" &
DrugUse_Drv2 == "No Apparent Influence" ~ "No Apparent Influence"))
# DATA PREPROCESSING IV: AGE CATEGORIES
dat$age.cat <- case_when(dat$Age_Drv1 >= 0 &
dat$Age_Drv1 <= 18 ~ "Youth",
dat$Age_Drv1 >= 19 &
dat$Age_Drv1 <= 25 ~ "Young Adult",
dat$Age_Drv1 >= 26 &
dat$Age_Drv1 <= 64 ~ "Adult",
dat$Age_Drv1 >= 65 ~ "Senior")
```
Day & Time
=====================================
Inputs {.sidebar}
-------------------------------------
```{r}
checkboxGroupInput("days",
label = h3("Day of Week"),
choices = list("Monday" = "Mon",
"Tuesday" = "Tue",
"Wednesday" = "Wed",
"Thursday" = "Thu",
"Friday" = "Fri",
"Saturday" = "Sat",
"Sunday" = "Sun" ),
selected = c("Fri",
"Sat",
"Sun")) #Selected is the default that loads
sliderInput(inputId = "hour", #column variable it is based off of
label = h3("Time of Day"), #What is h3?
min = 0,
max = 23,
value = c(6, 12)) #This is the default that loads
```
Outputs
-------------------------------------
### Traffic Accidents By Day and Time
```{r}
# LEAFLET MAPPING
renderLeaflet({
d2 <- dat %>%
filter(day %in% input$days,
hour >= input$hour[1],
hour <= input$hour[2])
d2$col.vec <- ifelse(test = d2$nohurt,
yes = "gray20",
no = ifelse(test = d2$inj,
yes = "steelblue",
no = "darkorange") )
point.size <- d2$Totalinjuries + d2$Totalfatalities
crash.details <- paste0("Time: ", d2$DateTime, "<br>",
"Total Fatalities: ", d2$Totalfatalities, "<br>",
"Total Injuries: ", d2$Totalinjuries, "<br>",
"Collision type: ", d2$Collisionmanner)
tempe <- leaflet( ) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -111.9278,
lat = 33.39951,
zoom = 13)
addCircles(tempe,
lng = d2$Longitude,
lat = d2$Latitude,
fillColor = d2$col.vec,
fillOpacity = 0.5,
stroke = FALSE,
radius = 50 * (1 + 0.33 * point.size),
popup = crash.details)
})
```
Age, Gender, & Method {data-orientation=rows}
=====================================
Sidebar {.sidebar}
-------------------------------------
Driver Characteristics
```{r}
sliderInput(inputId = "d1age",
label = h4("Driver 1 Age"),
min = 15,
max = 100,
value = c(18,36) )
sliderInput(inputId = "d2age",
label = h4("Driver 2 Age"),
min = 15,
max = 100,
value = c(18,36) )
selectInput(inputId = "d1gender",
label = h4("Driver 1 Gender"),
choices = c("Male",
"Female",
"Unknown"),
selected = "Male")
selectInput(inputId = "d2gender",
label = h4("Driver 2 Gender"),
choices = c("Male",
"Female",
"Unknown"),
selected = "Male")
radioButtons(inputId = "d1pedcy",
label = h4("Driver 1 Transportation"),
choices = c("Driver",
"Pedalcyclist",
"Pedestrian"),
selected = "Driver")
radioButtons(inputId = "d2pedcy",
label = h4("Driver 2 Transportation"),
choices = c("Driver",
"Pedalcyclist",
"Pedestrian"),
selected = "Driver")
```
Row
-------------------------------------
### Number of Crashes
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy )
crashes <- count(d2)
valueBox(crashes,
icon = "fa-solid fa-car-burst",
color = ifelse(test = crashes > 50,
yes = "danger",
no = "primary") )
})
```
### Total Injuries
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
total.injuries <- sum(d2$Totalinjuries)
valueBox(total.injuries,
icon = "fa-solid fa-user-injured",
color = ifelse(test = total.injuries > 30,
yes = "danger",
no = "primary" ))
})
```
### Total Fatalities
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
total.fatalities <- sum(d2$Totalfatalities)
valueBox(total.fatalities,
icon = "fa-solid fa-skull",
color = ifelse(test = total.fatalities > 10,
yes = "danger",
no = "primary"))
})
```
### Rate of Harm
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
rate.of.harm <- round(length(which(d2$harm == "Harm")) / count(d2), 3)
valueBox(rate.of.harm,
icon = "fa-solid fa-percent",
color = ifelse(test = rate.of.harm > 0.5,
yes = "danger",
no = "primary"))
})
```
Outputs
-------------------------------------
### Traffic Accidents by Driver Characteristics
```{r}
renderLeaflet({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
d2$col.vec <- ifelse(test = d2$nohurt,
yes = "gray20",
no = ifelse(test = d2$inj,
yes = "steelblue",
no = "darkorange") )
point.size <- d2$Totalinjuries + d2$Totalfatalities
crash.details <- paste0("Time: ", d2$DateTime, "<br>",
"Total Fatalities: ", d2$Totalfatalities, "<br>",
"Total Injuries: ", d2$Totalinjuries, "<br>",
"Collision type: ", d2$Collisionmanner)
tempe <- leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -111.9278,
lat = 33.39951,
zoom = 13)
addCircles(tempe,
lng = d2$Longitude,
lat = d2$Latitude,
fillColor = d2$col.vec,
fillOpacity = 0.5,
stroke = FALSE,
radius = 50 * (1 + 0.33 * point.size),
popup = crash.details)
})
```
Comparisons {data-orientation=rows}
=====================================
Sidebar {.sidebar}
-------------------------------------
Driver Characteristics
```{r}
sliderInput(inputId = "driver.1.age",
label = h4("Driver 1 Age"),
min = 15,
max = 100,
value = c(18, 36))
sliderInput(inputId = "driver.2.age",
label = h4("Driver 2 Age"),
min = 15,
max = 100,
value = c(18, 36))
selectInput(inputId = "driver.1.gender",
label = h4("Driver 1 Gender"),
choices = c("Male",
"Female",
"Unknown"),
selected = "Male")
selectInput(inputId = "driver.2.gender",
label = h4("Driver 2 Gender"),
choices = c("Male",
"Female",
"Unknown"),
selected = "Male")
radioButtons(inputId = "driver.1.pedcy",
label = h4("Driver 1 Transportation"),
choices = c("Driver",
"Pedalcyclist",
"Pedestrian"),
selected = "Driver")
radioButtons(inputId = "driver.2.pedcy",
label = h4("Driver 2 Transportation"),
choices = c("Driver",
"Pedalcyclist",
"Pedestrian"),
selected = "Driver")
```
Row
-------------------------------------
### Number of Crashes
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1] & Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1] & Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy )
crashes <- count(d2)
valueBox(crashes,
icon = "fa-solid fa-car-burst",
color = ifelse( crashes > 50, "danger", "primary") )
})
```
### Total Injuries
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1] & Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1] & Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
total.injuries <- sum(d2$Totalinjuries)
valueBox(total.injuries,
icon = "fa-solid fa-user-injured",
color = ifelse(total.injuries > 30, "danger", "primary"))
})
```
### Total Fatalities
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
total.fatalities <- sum(d2$Totalfatalities)
valueBox(total.fatalities,
icon = "fa-solid fa-skull",
color = ifelse(test = total.fatalities > 10,
yes = "danger",
no = "primary"))
})
```
### Rate of Harm
```{r}
renderValueBox({
d2 <- dat %>%
filter(Age_Drv1 >= input$d1age[1],
Age_Drv1 <= input$d1age[2],
Age_Drv2 >= input$d2age[1],
Age_Drv2 <= input$d2age[2],
Gender_Drv1 %in% input$d1gender,
Gender_Drv2 %in% input$d2gender,
Unittype_One %in% input$d1pedcy,
Unittype_Two %in% input$d2pedcy)
rate.of.harm <- round(length(which(d2$harm == "Harm")) / count(d2), 3)
valueBox(rate.of.harm,
icon = "fa-percent",
color = ifelse(test = rate.of.harm > 0.5,
yes = "danger",
no = "primary"))
})
```
Column
-------------------------------------
### Driver 1
```{r}
renderLeaflet({
d10 <- dat %>%
filter(Age_Drv1 >= input$driver.1.age[1],
Age_Drv1 <= input$driver.1.age[2],
Gender_Drv1 %in% input$driver.1.gender,
Unittype_One %in% input$driver.1.pedcy )
d10$col.vec <- ifelse(test = d10$nohurt,
yes = "gray20",
no = ifelse(test = d10$inj,
yes = "steelblue",
no = "darkorange"))
point.size <- d10$Totalinjuries + d10$Totalfatalities
crash.details <- paste0("Time: ", d10$DateTime, "<br>",
"Total Fatalities: ", d10$Totalfatalities, "<br>",
"Total Injuries: ", d10$Totalinjuries, "<br>",
"Collision type: ", d10$Collisionmanner)
tempe <- leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -111.9278,
lat = 33.39951,
zoom = 13)
addCircles(tempe,
lng = d10$Longitude,
lat = d10$Latitude,
fillColor = d10$col.vec,
fillOpacity = 0.5,
stroke = FALSE,
radius = 50 * (1 + 0.33 * point.size),
popup = crash.details)
})
```
### Driver 2
```{r}
renderLeaflet({
d11 <- dat %>%
filter(Age_Drv2 >= input$driver.2.age[1],
Age_Drv2 <= input$driver.2.age[2],
Gender_Drv2 %in% input$driver.2.gender,
Unittype_Two %in% input$driver.2.pedcy)
d11$col.vec <- ifelse(test = d11$nohurt,
yes = "gray20",
no = ifelse(test = d11$inj,
yes = "steelblue",
no = "darkorange"))
point.size2 <- d11$Totalinjuries + d11$Totalfatalities
crash.details2 <- paste0("Time: ", d11$DateTime, "<br>",
"Total Fatalities: ", d11$Totalfatalities, "<br>",
"Total Injuries: ", d11$Totalinjuries, "<br>",
"Collision type: ", d11$Collisionmanner)
tempe2 <- leaflet() %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -111.9278,
lat = 33.39951,
zoom = 13)
addCircles(tempe2,
lng = d11$Longitude,
lat = d11$Latitude,
fillColor = d11$col.vec,
fillOpacity = 0.5,
stroke = FALSE,
radius = 50 * (1 + 0.33 * point.size2),
popup = crash.details2 )
})
```
Year & Harm
=====================================
Inputs {.sidebar}
-------------------------------------
```{r}
checkboxGroupInput("Year",
label = h3("Year"),
choices = list(2012,
2013,
2014,
2015,
2016,
2017,
2018),
selected = c(2012, 2013, 2014, 2015, 2016, 2017, 2018))
checkboxGroupInput(inputId = ("level_of_harm"),
label = h3("Type of Accident"),
choices = list("Harmless" = "nohurt",
"Injurious (No Fatalities)" = "inj",
"Fatal" = "fatal"),
selected = c("nohurt", "inj", "fatal"))
```
Outputs
-------------------------------------
### Number of Accidents by Year & Harm
```{r}
renderTable({
req(input$Year)
filtered_data <- dat %>%
filter(Year %in% input$Year)
aggregated_data <- filtered_data %>%
group_by(Year) %>%
summarize(
"Fatal Accidents" = sum(fatal, na.rm = TRUE),
"Injurious Accidents" = sum(inj, na.rm = TRUE),
"Harmless Accidents" = sum(nohurt, na.rm = TRUE),
"Total Accidents" = sum(fatal, inj, nohurt, na.rm = TRUE),
"Proportion Fatal (%)" = mean(fatal, na.rm = TRUE)*100,
"Proportion Injurious (%)" = mean(inj, na.rm = TRUE)*100,
"Proportion Harmless (%)"= mean(nohurt, na.rm = TRUE)*100,
.groups = 'drop')
harm_selection <- c("Year", "Total Accidents")
if("fatal" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Fatal Accidents")
}
if("inj" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Injurious Accidents")
}
if("nohurt" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Harmless Accidents")
}
selected_data <- aggregated_data[, harm_selection, drop = FALSE]
selected_data
})
```
### Proportion of Accidents by Year & Harm
```{r}
renderTable({
req(input$Year)
filtered_data <- dat %>%
filter(Year %in% input$Year)
aggregated_data <- filtered_data %>%
group_by(Year) %>%
summarize(
"Fatal Accidents" = sum(fatal, na.rm = TRUE),
"Injurious Accidents" = sum(inj, na.rm = TRUE),
"Harmless Accidents" = sum(nohurt, na.rm = TRUE),
"Total Accidents" = sum(fatal, inj, nohurt, na.rm = TRUE),
"Proportion Fatal (%)" = mean(fatal, na.rm = TRUE)*100,
"Proportion Injurious (%)" = mean(inj, na.rm = TRUE)*100,
"Proportion Harmless (%)"= mean(nohurt, na.rm = TRUE)*100,
.groups = 'drop')
harm_selection <- c("Year")
if("fatal" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Proportion Fatal (%)")
}
if("inj" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Proportion Injurious (%)")
}
if("nohurt" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Proportion Harmless (%)")
}
selected_data <- aggregated_data[, harm_selection, drop = FALSE]
colnames(selected_data) <- gsub("_", " ", colnames(selected_data))
selected_data
})
```
### Plotted Proportions of Accidents by Year & Harm
```{r}
renderPlot({
req(input$Year)
filtered_data <- dat %>%
filter(Year %in% input$Year)
aggregated_data <- filtered_data %>%
group_by(Year) %>%
summarize(
"Fatal Accidents" = sum(fatal, na.rm = TRUE),
"Injurious Accidents" = sum(inj, na.rm = TRUE),
"Harmless Accidents" = sum(nohurt, na.rm = TRUE),
"Total Accidents" = sum(fatal, inj, nohurt, na.rm = TRUE),
"Proportion Fatal (%)" = mean(fatal, na.rm = TRUE)*100,
"Proportion Injurious (%)" = mean(inj, na.rm = TRUE)*100,
"Proportion Harmless (%)"= mean(nohurt, na.rm = TRUE)*100,
.groups = 'drop')
harm_selection <- c("Year")
if("fatal" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Proportion Fatal (%)")
}
if("inj" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Proportion Injurious (%)")
}
if("nohurt" %in% input$level_of_harm) {
harm_selection <- c(harm_selection, "Proportion Harmless (%)")
}
selected_data <- aggregated_data[, harm_selection, drop = FALSE]
colnames(selected_data) <- gsub("_", " ", colnames(selected_data))
long_data <- selected_data %>%
tidyr::pivot_longer(-Year, names_to = "Category", values_to = "Proportion")
ggplot(long_data, aes(x = Year, y = Proportion, fill = Category)) +
geom_area(position = 'stack') +
labs(title = "Proportion of Harm Year-over-Year",
x = "Year",
y = "Proportion (%)",
fill = "Level of Harm") +
theme_minimal()
})
```
Substance Use
=====================================
Inputs {.sidebar}
-------------------------------------
```{r}
selectInput(
inputId = "D1substanceFilter",
label = h3("Substance (Driver One):"),
choices = c("All", "Alcohol", "Drugs", "Alcohol and Drugs", "No Apparent Influence"),
selected = "All")
selectInput(
inputId = "timeOfDay",
label = h3("Select Time of Day:"),
choices = c("All", "Morning Commute", "Evening Commute", "School Pickup", "Work", "Night", "Midnight to Dawn"),
selected = "All")
```
Outputs
-------------------------------------
### Substance Use, Harm, Time Periods
```{r}
renderLeaflet({
filtered_data <- dat %>%
filter((input$D1substanceFilter == "All" | d1.substance == input$D1substanceFilter) &
(input$timeOfDay == "All" | time.of.day == input$timeOfDay))
col.vec <- ifelse(filtered_data$nohurt,
"gray25",
ifelse(filtered_data$inj,
"orange",
"red"))
point.size <- filtered_data$Totalinjuries + filtered_data$Totalfatalities
crash.details <- paste0("Time: ", filtered_data$DateTime, "<br>",
"Total Fatalities: ", filtered_data$Totalfatalities, "<br>",
"Total Injuries: ", filtered_data$Totalinjuries, "<br>",
"Collision type: ", filtered_data$Collisionmanner)
tempe <- leaflet(filtered_data) %>%
addProviderTiles("CartoDB.Positron") %>%
setView(lng = -111.9278, lat = 33.4265, zoom = 13)
tempe %>%
addCircles(lng = ~Longitude,
lat = ~Latitude,
fillColor = ~col.vec,
fillOpacity = 0.5,
stroke = FALSE,
radius = ~50 * (1 + 0.33 * point.size),
popup = ~crash.details) %>%
addLegend("topright",
colors = c("red", "orange"),
labels = c("Fatal", "Injurious"),
title = "Accident Severity",
opacity = 1)
})
```
About
=====================================
Row
-------------------------------------
### About this Dashboard
* The data utilized is available [here.](https://github.com/DS4PS/Data) For the most up-to-date data, visit the [City of Tempe](https://data.tempe.gov/datasets/tempegov::1-08-crash-data-report-detail/about) website.
* This data contains traffic accident reports that occurred between 2012 and 2018 in Tempe, Arizona. The data is used by local government to reduce accidents resulting in fatalities and serious injury. It is used to improve safety in the city.
* This dashboard serves as a tool to explore and examine traffic accidents in Tempe, Arizona. Diving into this dashboard will shed light on accident patterns by day, time, year, age, gender, type of transportation, and substance use. Although this is not a comprehensive view of all the data variables at play, it will serve its purpose for introductory exploration. Please note, "harmless" as it is used in the context of this dashboard, refers specifically to accidents that were not classifed as causing injuries or fatalities.
Tab Breakdown:
* Day & Time: Use the map to visualize traffic accidents by the time of day and day of the week.
* Age, Gender, & Method: This tab allows you to visually explore accidents based on the drivers characteristics, including age, gender, and type of transportation.
* Comparisons: Create distinct maps for each driver to further isolate accidents using the variables of Age, Gender, & Method
* Year & Harm: Compare rates of accidents across the years, including proportions of fatal, injurious, and harmless accidents.
* Substance Use: View a map of accidents by the involvement of substances within common traffic periods.
### Dashboard Author
* [Sean West](https://www.linkedin.com/in/seanawest/) | Program Evaluation & Data Analytics, MS
* Recognition to Dr. Jesse Lecy for creating this dashboard from which additional tabs were built.
Row
-------------------------------------
DATA DICTIONARY
```{r}
url.dd <- paste0("https://raw.githubusercontent.com",
"/DS4PS/cpp-526-fall-2019/master/l",
"abs/final-project/TempeTrafficAcc",
"identsDataDictionary.csv")
data.dictionary <- read.csv(url.dd,
stringsAsFactors = FALSE)
data.dictionary$description <- stringi::stri_trans_general(data.dictionary$description,
"latin-ascii")
data.dictionary %>%
select(column, description) %>%
pander()
```
Data
=====================================
```{r}
these.buttons <- c("copy",
"csv",
"pdf",
"print")
renderDataTable({
datatable(dat[1:100, ],
filter = "bottom",
rownames = FALSE,
fillContainer = TRUE,
style = "bootstrap",
class = "table-condensed table-striped",
extensions = "Buttons",
options = list(dom = "Bfrtip",
buttons = these.buttons))
})
```