Tornado are one of the most destructive forces in nature, causing signficant damage to property, infrastructure, and lives. Understanding their spatial patterns can assist researchers, policymakers, and emergency management teams make more informed decisions and prepare for future touchdowns. This report analyzes tornado activity in Oklahoma from 2016 to 2021, focusing on tornado paths, touchdown points, and densisty patterns. The analysis is composed of three portions:
Tornado Paths and Points- Points representing individual tornado occurrences while paths depict the trajectory the tornado as it moves across the landscape. Each year is color-coded to identify patterns and highlight recurring activity.
Tornado Density by County and Year- Tornado density is summarized at the county level for each year from 2016-2021, Through aggregating the tornado data to counties researchers gain insight into spatial variations in tornado frequency within Oklahoma. Each panel of the faceted map represents tornado density per year allowing for year over year analysis of trends and hotspots.
Choropleth Maps of Tornado Density- These maps depict tornado density broken into county classifications. These maps are combined into a single composite figure allowing for side by side comparisons revealing patterns in tornado density across Oklahoma.
The goal of this portion of the assignment is to visualize tornado paths and points from 2016–2021, with each color representing a different year. This visualization helps identify patterns of tornado occurrences over time and provides a clearer understanding of how tornadoes move across the landscape. The composite figure created combines tornado points and paths, offering a comprehensive overview of tornado activity during this time period.
#Load libraries ----
library(sf)
library(ggplot2)
library(dplyr)
library(tidyr)
library(scales)
library(RColorBrewer)
library(units)
library(cowplot)
# Set the work directory----
setwd("C:\\Users\\ranse\\OneDrive\\Desktop\\GEOG_588\\Lab4\\Lesson4_Data")
#Load the shapefiles ----
okcounty <- st_read("ok_counties.shp", quiet = TRUE)
tpoint <- st_read("ok_tornado_point.shp", quiet = TRUE)
tpath <- st_read("ok_tornado_path.shp", quiet = TRUE)
class(okcounty)
# Filter tornado data
tpoint_16_21 <- tpoint%>%
filter(yr >= 2016 & yr <= 2021) %>%
select(om, yr, date)
tpath_16_21 <- tpath %>%
filter(yr >= 2016 & yr <= 2021) %>%
select(om, yr, date)
# Visualize Tornado Point Data by Year
tornado_points_map <- ggplot() +
geom_sf(data = okcounty, fill = NA) +
geom_sf(data = tpoint_16_21, aes(color = as.factor(yr))) +
scale_color_discrete(name = "Year") +
coord_sf(datum = NA) +
theme_void() +
labs(title = "Tornado Points (2016-2021)")
# Visualize Tornado Path Data by Year
tornado_paths_map <- ggplot() +
geom_sf(data = okcounty, fill = NA) +
geom_sf(data = tpath_16_21, aes(color = as.factor(yr)), size = 1) +
scale_color_discrete(name = "Year") +
theme_bw() +
labs(title = "Tornado Paths (2016-2021)")
#Combine the points and paths into a composite figure
tornado_composite_map <- plot_grid(
tornado_paths_map,
tornado_points_map,
ncol = 1,
labels = c("Figure 1.", "Figure 2."),
align = "v"
)
The purpose of this section of the assignment is to show county level tornado density in Oklahoma from 2016-2021. Each panel in the faceted map represents a designated year, with tornado densisty calculated per 1,000 square kilometers allowing for county comparisons. This visualization provides insights into annual trends and recurring hotspots, aiding in identifying areas most affected by tornado activity from 2016-2021.
# Calculate tornado density
countypnt <- st_join(tpoint_16_21, okcounty)
#Summarize torando counts by year and county
countypnt <- st_drop_geometry(countypnt)
countysum <- countypnt %>%
group_by(GEOID, yr) %>%
summarise(tcnt = n(), .groups = "drop")
# Add a column for area to okcounty
okcounty <- okcounty %>%
mutate(area = st_area(.) %>% drop_units()) # Calculate area once for each county
#Join Summary Data to the county map and calculate density
countymap <- okcounty %>%
left_join(countysum, by = "GEOID") %>%
replace(is.na(.), 0) %>% # Replace NA values with 0
mutate(tdens = 10^6 * 10^3 * tcnt / area)
# Faceted map of tornado density by year (this will not display inline)
ggplot(data = countymap) +
geom_sf(data = countymap, aes(fill = tdens)) + # Tornado density layer
geom_sf(data = okcounty, fill = NA, color = "black", size = 0.2) + # County boundaries
facet_wrap(vars(yr), ncol = 2) + # Facet by year
scale_fill_viridis_c(name = "Tornado Density\n(per 1,000 km²)") + # Viridis color scale
theme_void() + # Minimalistic theme
labs(
title = "County-Level Tornado Density (2016-2021)",
subtitle = "Faceted by year with county boundaries",
caption = "Data Source: Oklahoma Tornado Dataset"
)
This section of the assignment focuses on four choropleth maps of tornado density in Oklahoma using quantile classification with class numbers ranging from 3 to 6. Each map illustrates how the number of classes influences the visualization of spatial patterns, with fewer classes emphasizing broader trends and more classes revealing finer variations. These maps are compared to explore how classification choices impact the interpretation of tornado density across the state.
# Create chloropleth Maps
create_choropleth <- function(countymap, n_classes) {
ggplot(data = countymap) +
geom_sf(aes(fill = tdens), color = "white", size = 0.1) +
scale_fill_distiller(
palette = "YlOrRd",
direction = 1,
breaks = scales::pretty_breaks(n = n_classes),
labels = scales::comma,
na.value = "grey90",
name = "Tornado Density"
) +
theme_void() +
theme(legend.position = "bottom") +
labs(title = paste(n_classes, "Quantile Classes"))
}
# Add county boundaries to the choropleth maps and save
map_3 <- create_choropleth(countymap, 3) +
geom_sf(data = okcounty, fill = NA, color = "black", size = 0.2) # Add boundaries
map_4 <- create_choropleth(countymap, 4) +
geom_sf(data = okcounty, fill = NA, color = "black", size = 0.2) # Add boundaries
map_5 <- create_choropleth(countymap, 5) +
geom_sf(data = okcounty, fill = NA, color = "black", size = 0.2) # Add boundaries
map_6 <- create_choropleth(countymap, 6) +
geom_sf(data = okcounty, fill = NA, color = "black", size = 0.2) # Add boundaries
# Create a composite figure with the updated maps
composite_figure_with_boundaries <- plot_grid(
map_3, map_4, map_5, map_6,
ncol = 2, align = "v"
)