This report analyzes the U.S. National Oceanic and Atmospheric Administration (NOAA) Storm Database to identify which types of severe weather events are most harmful to population health and which have the greatest economic consequences. The raw data span 1950 to November 2011 and record fatalities, injuries, and property/crop damage estimates by event type (EVTYPE). After loading the raw compressed CSV file directly into R, the event-type field was standardized, and property/crop damage values were converted to dollar amounts using their associated magnitude codes (K, M, B, etc.). Health impact was assessed by summing fatalities and injuries per event type, and economic impact was assessed by summing property and crop damage per event type. The results show that tornadoes are by far the leading cause of both fatalities and injuries, while floods cause the greatest total economic damage, with hurricanes/typhoons and tornadoes also ranking among the costliest event types. These findings can help government and municipal managers prioritize resources for severe weather preparedness.
The analysis starts directly from the raw, compressed CSV file provided by the course. If the file is not already present in the working directory, it is downloaded automatically. The file is read directly from its .bz2 compressed form using bzfile(), with no manual/external preprocessing.
library(dplyr)
library(ggplot2)
library(gridExtra)
library(knitr)
library(scales)
dataFile <- "StormData.csv.bz2"
if (!file.exists(dataFile)) {
download.file(
"https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2",
destfile = dataFile, method = "libcurl", mode = "wb"
)
}
storm <- read.csv(bzfile(dataFile), stringsAsFactors = FALSE)
dim(storm)
## [1] 902297 37
str(storm[, c("BGN_DATE","EVTYPE","FATALITIES","INJURIES","PROPDMG","PROPDMGEXP","CROPDMG","CROPDMGEXP")])
## 'data.frame': 902297 obs. of 8 variables:
## $ BGN_DATE : chr "4/18/1950 0:00:00" "4/18/1950 0:00:00" "2/20/1951 0:00:00" "6/8/1951 0:00:00" ...
## $ EVTYPE : chr "TORNADO" "TORNADO" "TORNADO" "TORNADO" ...
## $ FATALITIES: num 0 0 0 0 0 0 0 0 1 0 ...
## $ INJURIES : num 15 0 2 2 2 6 1 0 14 0 ...
## $ PROPDMG : num 25 2.5 25 2.5 2.5 2.5 2.5 2.5 25 25 ...
## $ PROPDMGEXP: chr "K" "K" "K" "K" ...
## $ CROPDMG : num 0 0 0 0 0 0 0 0 0 0 ...
## $ CROPDMGEXP: chr "" "" "" "" ...
For this analysis we only need the event type and the health/economic impact variables, so we subset the data to reduce memory overhead.
storm2 <- storm %>%
select(EVTYPE, FATALITIES, INJURIES, PROPDMG, PROPDMGEXP, CROPDMG, CROPDMGEXP)
The EVTYPE field contains inconsistent capitalization and extra whitespace (e.g. “TSTM WIND”, “tstm wind”, “Thunderstorm Wind”), which would otherwise fragment identical event types into separate categories. We standardize case and trim whitespace. A full free-text remapping of all ~900 raw EVTYPE values to the 48 official categories is beyond the scope of this report, but basic normalization substantially reduces duplication and is sufficient to identify the top contributing event types, since the highest-impact categories are already recorded fairly consistently in the raw data.
storm2$EVTYPE <- trimws(toupper(storm2$EVTYPE))
PROPDMG/CROPDMG give a numeric magnitude, and PROPDMGEXP/CROPDMGEXP give a multiplier code (per the NWS documentation: K = thousand, M = million, B = billion; numeric digits and a few stray symbols also appear in the raw data and are treated as powers of ten or as unknown/zero respectively, following the commonly used convention for this dataset).
expToMultiplier <- function(exp) {
exp <- toupper(trimws(exp))
case_when(
exp == "K" ~ 1e3,
exp == "M" ~ 1e6,
exp == "B" ~ 1e9,
exp == "H" ~ 1e2,
exp %in% as.character(0:9) ~ 10^as.numeric(exp),
TRUE ~ 0 # blank, "-", "+", "?" and other undocumented codes treated as no valid multiplier
)
}
storm2 <- storm2 %>%
mutate(
propMultiplier = expToMultiplier(PROPDMGEXP),
cropMultiplier = expToMultiplier(CROPDMGEXP),
propDamageUSD = PROPDMG * propMultiplier,
cropDamageUSD = CROPDMG * cropMultiplier,
totalDamageUSD = propDamageUSD + cropDamageUSD
)
We compute, for each event type, the total fatalities, total injuries, and total economic damage (property + crop), then extract the top 10 event types for each impact measure.
healthByEvent <- storm2 %>%
group_by(EVTYPE) %>%
summarise(
totalFatalities = sum(FATALITIES, na.rm = TRUE),
totalInjuries = sum(INJURIES, na.rm = TRUE),
.groups = "drop"
) %>%
mutate(totalHealthImpact = totalFatalities + totalInjuries) %>%
arrange(desc(totalHealthImpact))
top10Fatalities <- healthByEvent %>% arrange(desc(totalFatalities)) %>% slice(1:10)
top10Injuries <- healthByEvent %>% arrange(desc(totalInjuries)) %>% slice(1:10)
economicByEvent <- storm2 %>%
group_by(EVTYPE) %>%
summarise(
totalPropDamage = sum(propDamageUSD, na.rm = TRUE),
totalCropDamage = sum(cropDamageUSD, na.rm = TRUE),
totalDamage = sum(totalDamageUSD, na.rm = TRUE),
.groups = "drop"
) %>%
arrange(desc(totalDamage))
top10Damage <- economicByEvent %>% slice(1:10)
The tables below show the ten event types responsible for the most fatalities and the most injuries, respectively, across the full 1950-2011 record.
kable(top10Fatalities %>% select(EVTYPE, totalFatalities),
col.names = c("Event Type", "Total Fatalities"),
caption = "Top 10 event types by total fatalities")
| Event Type | Total Fatalities |
|---|---|
| TORNADO | 5633 |
| EXCESSIVE HEAT | 1903 |
| FLASH FLOOD | 978 |
| HEAT | 937 |
| LIGHTNING | 816 |
| TSTM WIND | 504 |
| FLOOD | 470 |
| RIP CURRENT | 368 |
| HIGH WIND | 248 |
| AVALANCHE | 224 |
kable(top10Injuries %>% select(EVTYPE, totalInjuries),
col.names = c("Event Type", "Total Injuries"),
caption = "Top 10 event types by total injuries")
| Event Type | Total Injuries |
|---|---|
| TORNADO | 91346 |
| TSTM WIND | 6957 |
| FLOOD | 6789 |
| EXCESSIVE HEAT | 6525 |
| LIGHTNING | 5230 |
| HEAT | 2100 |
| ICE STORM | 1975 |
| FLASH FLOOD | 1777 |
| THUNDERSTORM WIND | 1488 |
| HAIL | 1361 |
Figure 1 below presents these same results graphically as a two-panel bar chart, making it easy to compare the leading causes of death and injury side by side.
p1 <- ggplot(top10Fatalities, aes(x = reorder(EVTYPE, totalFatalities), y = totalFatalities)) +
geom_col(fill = "firebrick") +
coord_flip() +
labs(title = "Top 10 Causes of Fatalities", x = "Event Type", y = "Total Fatalities") +
theme_minimal()
p2 <- ggplot(top10Injuries, aes(x = reorder(EVTYPE, totalInjuries), y = totalInjuries)) +
geom_col(fill = "darkorange") +
coord_flip() +
labs(title = "Top 10 Causes of Injuries", x = "Event Type", y = "Total Injuries") +
theme_minimal()
grid.arrange(p1, p2, ncol = 2)
Figure 1. Top 10 severe weather event types in the United States (1950-2011) ranked by total fatalities (left panel) and total injuries (right panel). Tornadoes are the leading cause of both fatalities and injuries by a wide margin.
Across the United States, tornadoes are clearly the most harmful event type to population health, causing far more fatalities and injuries than any other category, followed by excessive heat and flash floods/thunderstorm winds for fatalities, and thunderstorm wind/flood-related events for injuries.
The table below shows the ten event types with the greatest combined property and crop damage.
top10Damage_display <- top10Damage %>%
mutate(
`Property Damage ($)` = dollar(totalPropDamage),
`Crop Damage ($)` = dollar(totalCropDamage),
`Total Damage ($)` = dollar(totalDamage)
) %>%
select(EVTYPE, `Property Damage ($)`, `Crop Damage ($)`, `Total Damage ($)`)
kable(top10Damage_display, col.names = c("Event Type", "Property Damage ($)", "Crop Damage ($)", "Total Damage ($)"),
caption = "Top 10 event types by total economic damage (property + crop)")
| Event Type | Property Damage ($) | Crop Damage ($) | Total Damage ($) |
|---|---|---|---|
| FLOOD | $144,657,709,800 | $5,661,968,450 | $150,319,678,250 |
| HURRICANE/TYPHOON | $69,305,840,000 | $2,607,872,800 | $71,913,712,800 |
| TORNADO | $56,947,380,614 | $414,953,270 | $57,362,333,884 |
| STORM SURGE | $43,323,536,000 | $5,000 | $43,323,541,000 |
| HAIL | $15,735,267,456 | $3,025,954,470 | $18,761,221,926 |
| FLASH FLOOD | $16,822,723,772 | $1,421,317,100 | $18,244,040,872 |
| DROUGHT | $1,046,106,000 | $13,972,566,000 | $15,018,672,000 |
| HURRICANE | $11,868,319,010 | $2,741,910,000 | $14,610,229,010 |
| RIVER FLOOD | $5,118,945,500 | $5,029,459,000 | $10,148,404,500 |
| ICE STORM | $3,944,927,860 | $5,022,113,500 | $8,967,041,360 |
Figure 2 shows the total economic damage (in billions of dollars) for the top 10 event types.
ggplot(top10Damage, aes(x = reorder(EVTYPE, totalDamage), y = totalDamage / 1e9)) +
geom_col(fill = "steelblue") +
coord_flip() +
labs(title = "Top 10 Event Types by Total Economic Damage",
x = "Event Type", y = "Total Damage (Billions of USD)") +
theme_minimal()
Figure 2. Top 10 severe weather event types in the United States (1950-2011) ranked by total economic damage (property plus crop damage, in billions of dollars). Floods have caused the greatest cumulative economic damage, with hurricanes/typhoons and tornadoes also among the most costly event types.
Across the United States, floods have caused the greatest total economic damage over the period covered by the database, followed by hurricanes/typhoons and tornadoes. Property damage is the dominant component of total economic loss for most of the top event types, though certain categories (e.g. droughts) contribute disproportionately through crop damage.
Tornadoes represent the single greatest threat to public health among severe weather events in the United States, while floods, hurricanes/typhoons, and tornadoes represent the greatest sources of economic loss. These findings suggest that resource prioritization for severe weather preparedness should weight both the historically high human toll of tornadoes and the substantial economic exposure associated with flooding and tropical storm systems.