This assignment focuses on analysing the NOAA Storm Database and explore the effects of wheather events on both population and economy. The database includes data from 1950 to November 2011.
The analysis presented below focuses on wheather damages in respect to health (fatalities and injuries) and economic consequences (property and crops)
Detailed documentation of the database can be found here
First of all, load the necessary libraries
knitr::opts_chunk$set(echo = TRUE, fig.path = "figures/")
library(ggplot2)
## Warning: il pacchetto 'ggplot2' è stato creato con R versione 4.5.3
library(paletteer)
## Warning: il pacchetto 'paletteer' è stato creato con R versione 4.5.3
library(tidyr)
## Warning: il pacchetto 'tidyr' è stato creato con R versione 4.5.3
library(dplyr)
## Warning: il pacchetto 'dplyr' è stato creato con R versione 4.5.3
##
## Caricamento pacchetto: 'dplyr'
## I seguenti oggetti sono mascherati da 'package:stats':
##
## filter, lag
## I seguenti oggetti sono mascherati da 'package:base':
##
## intersect, setdiff, setequal, union
Load the unzipped dataset. Given the size of the dataset and the scope of this analysis, the code below pre-select the variables of interest: event type, fatalities, injuries, property damage, property damage cost, crop damage, crop damage cost. It also filters out rows with unknown label (“?”)
storm_data <- read.csv("repData_data_StormData.csv") %>%
select(EVTYPE, FATALITIES, INJURIES, PROPDMG, PROPDMGEXP, CROPDMG, CROPDMGEXP) %>%
filter(EVTYPE != "?")
Events causing neither a death nor an injury are removed before totalling by event type. The ten worst events are kept and reshaped to long form, with the bar order fixed by the combined total.
health <- storm_data %>%
filter(FATALITIES > 0 | INJURIES > 0) %>%
group_by(EVTYPE) %>%
summarise(
Fatalities = sum(FATALITIES),
Injuries = sum(INJURIES),
.groups = "drop"
) %>%
mutate(Total = Fatalities + Injuries) %>%
slice_max(Total, n = 10) %>%
mutate(EVTYPE = factor(EVTYPE, levels = EVTYPE)) %>%
pivot_longer(-EVTYPE, names_to = "type", values_to = "value") %>%
mutate(type = factor(type, levels = c("Fatalities", "Injuries", "Total")))
Property and crop damage are each split across a value column and a
magnitude code. In the code column a single digit d means
10^d, while H, K, M
and B are hundreds, thousands, millions and billions,
respectively. Blanks and the stray -, +,
? symbols carry no multiplier. Multiplying the two columns
puts every record in dollars, after which the same aggregate-and-reshape
steps as before apply. For visualization purposes, costs are converted
to billions.
dmg_key <- c(setNames(10^(0:9), 0:9), H = 1e2, K = 1e3, M = 1e6, B = 1e9)
economic <- storm_data %>%
filter(PROPDMG > 0 | CROPDMG > 0) %>%
mutate(
Property = PROPDMG * coalesce(unname(dmg_key[toupper(PROPDMGEXP)]), 1),
Crop = CROPDMG * coalesce(unname(dmg_key[toupper(CROPDMGEXP)]), 1)
) %>%
group_by(EVTYPE) %>%
summarise(across(c(Property, Crop), sum), .groups = "drop") %>%
mutate(Total = Property + Crop) %>%
slice_max(Total, n = 10) %>%
mutate(EVTYPE = factor(EVTYPE, levels = EVTYPE)) %>%
pivot_longer(-EVTYPE, names_to = "type", values_to = "value") %>%
mutate(
type = factor(type, levels = c("Property", "Crop", "Total")),
value = value / 1e9
)
ggplot(health, aes(x = EVTYPE, y = value, fill = type)) +
geom_col(position = "dodge") + theme_minimal() +
labs(x = "Event type", y = "People affected", fill = NULL,
title = "Most harmful weather events to population health") +
theme(text = element_text(size = 13), axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "inside",
legend.position.inside = c(1, 1),
legend.justification = c(1, 1)) + scale_fill_paletteer_d("LaCroixColoR::Lime")
ggplot(economic, aes(x = EVTYPE, y = value, fill = type)) +
geom_col(position = "dodge") +
scale_y_continuous() +
scale_fill_paletteer_d("LaCroixColoR::Lime") +
labs(x = NULL, y = "Damage (billions USD)", fill = NULL,
title = "Costliest weather events, 1950-2011") +
theme_minimal() +
theme(text = element_text(size = 13),
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "inside",
legend.position.inside = c(1, 1),
legend.justification = c(1, 1),
panel.grid.major.x = element_blank())