Synopsis

This report analyzes the U.S. National Oceanic and Atmospheric Administration’s (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 database covers events recorded between 1950 and November 2011. To assess public health impact, total fatalities and total injuries were aggregated by event type. To assess economic impact, property and crop damage estimates were converted from their raw magnitude codes (e.g. “K”, “M”, “B”) into dollar figures and summed by event type. Across the full record, tornadoes are responsible for by far the largest number of fatalities and injuries of any event type, making them the leading public health threat in this dataset. Floods and hurricanes/typhoons are responsible for the largest total economic damage, driven primarily by property damage, while droughts stand out as the leading cause of crop damage specifically. These findings suggest that resources for both emergency preparedness and economic mitigation planning should be weighted heavily toward tornado readiness and flood/hurricane protection.

Data Processing

Downloading and reading the raw data

The analysis begins from the original, compressed CSV file provided by the course. If the file is not already present in the working directory, it is downloaded here directly.

data_url <- "https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2"
data_file <- "StormData.csv.bz2"

if (!file.exists(data_file)) {
  download.file(data_url, destfile = data_file, mode = "wb", quiet = TRUE)
}

The compressed CSV is read directly with read.csv(), which can decompress .bz2 files natively via a bzfile() connection.

storm_raw <- read.csv(bzfile(data_file), stringsAsFactors = FALSE)
dim(storm_raw)
## [1] 902297     37

Selecting relevant variables

Only the columns needed to answer the two questions are kept: the event type, the health-impact variables (FATALITIES, INJURIES), and the economic-impact variables (PROPDMG, PROPDMGEXP, CROPDMG, CROPDMGEXP).

library(dplyr)

storm <- storm_raw %>%
  select(EVTYPE, FATALITIES, INJURIES, PROPDMG, PROPDMGEXP, CROPDMG, CROPDMGEXP)

Cleaning event type labels

EVTYPE contains many inconsistent labels (extra whitespace, mixed case, and some near-duplicate spellings). Whitespace is trimmed and labels are converted to uppercase so that, for example, "tornado", "Tornado", and "TORNADO " are treated as the same event type. This is a light-touch cleaning step; no attempt is made to merge every near-duplicate free-text variant, since doing so would require an extensive manual lookup table beyond the scope of this report, and the dominant categories (tornado, flood, wind, heat, etc.) are unaffected by this limitation.

storm$EVTYPE <- trimws(toupper(storm$EVTYPE))

Converting damage magnitude codes to dollar values

PROPDMGEXP and CROPDMGEXP store a multiplier code alongside the numeric PROPDMG/CROPDMG values: "K"/"k" = thousands, "M"/"m" = millions, "B"/"b" = billions, and digit characters represent powers of ten. Any other or blank code is treated as a multiplier of 1 (i.e., no scaling), following the NOAA documentation’s description of these fields as the source of the intended scale.

exp_to_multiplier <- function(code) {
  code <- toupper(trimws(code))
  case_when(
    code == "K" ~ 1e3,
    code == "M" ~ 1e6,
    code == "B" ~ 1e9,
    code %in% as.character(0:9) ~ 10^as.numeric(code),
    TRUE ~ 1
  )
}

storm <- storm %>%
  mutate(
    prop_dollars = PROPDMG * exp_to_multiplier(PROPDMGEXP),
    crop_dollars = CROPDMG * exp_to_multiplier(CROPDMGEXP),
    total_econ_dollars = prop_dollars + crop_dollars
  )

Aggregating by event type

For each cleaned event type, total fatalities, total injuries, total property damage, total crop damage, and combined economic damage are summed across all recorded events.

by_event <- storm %>%
  group_by(EVTYPE) %>%
  summarise(
    total_fatalities = sum(FATALITIES, na.rm = TRUE),
    total_injuries   = sum(INJURIES, na.rm = TRUE),
    total_health     = total_fatalities + total_injuries,
    total_prop       = sum(prop_dollars, na.rm = TRUE),
    total_crop       = sum(crop_dollars, na.rm = TRUE),
    total_econ       = sum(total_econ_dollars, na.rm = TRUE),
    .groups = "drop"
  )

Results

Question 1: Which event types are most harmful to population health?

The top 10 event types by combined fatalities and injuries are shown below.

top_health <- by_event %>%
  arrange(desc(total_health)) %>%
  slice_head(n = 10)

top_health
## # A tibble: 10 x 7
##    EVTYPE total_fatalities total_injuries total_health total_prop total_crop
##    <chr>             <dbl>          <dbl>        <dbl>      <dbl>      <dbl>
##  1 TORNA…             5633          91346        96979    5.69e10  414953270
##  2 EXCES…             1903           6525         8428    7.75e 6  492402000
##  3 TSTM …              504           6957         7461    4.49e 9  554007350
##  4 FLOOD               470           6789         7259    1.45e11 5661968450
##  5 LIGHT…              816           5230         6046    9.30e 8   12092090
##  6 HEAT                937           2100         3037    1.80e 6  401461500
##  7 FLASH…              978           1777         2755    1.68e10 1421317100
##  8 ICE S…               89           1975         2064    3.94e 9 5022113500
##  9 THUND…              133           1488         1621    3.48e 9  414843050
## 10 WINTE…              206           1321         1527    6.69e 9   26944000
## # … with 1 more variable: total_econ <dbl>
library(ggplot2)
library(tidyr)

health_long <- top_health %>%
  select(EVTYPE, total_fatalities, total_injuries) %>%
  pivot_longer(
    cols = c(total_fatalities, total_injuries),
    names_to = "measure",
    values_to = "count"
  ) %>%
  mutate(
    measure = recode(measure,
      total_fatalities = "Fatalities",
      total_injuries = "Injuries"
    ),
    EVTYPE = factor(EVTYPE, levels = rev(top_health$EVTYPE))
  )

ggplot(health_long, aes(x = EVTYPE, y = count, fill = measure)) +
  geom_col(position = "dodge") +
  coord_flip() +
  scale_fill_manual(values = c("Fatalities" = "#b5652d", "Injuries" = "#d7bfa6")) +
  labs(
    title = "Top 10 Event Types by Public Health Impact",
    x = "Event type",
    y = "Total count (1950-2011)",
    fill = NULL
  ) +
  theme_minimal(base_size = 12)

Figure 1. Total fatalities and total injuries by event type, for the ten event types with the highest combined health impact, 1950-2011.

Figure 1 shows total fatalities (dark bars) and total injuries (light bars) for the ten event types with the greatest combined health impact. TORNADO accounts for the largest combined total, with 5,633 fatalities and 91,346 injuries recorded across the period.

Question 2: Which event types have the greatest economic consequences?

The top 10 event types by combined property and crop damage are shown below, with dollar totals expressed in billions for readability.

top_econ <- by_event %>%
  arrange(desc(total_econ)) %>%
  slice_head(n = 10) %>%
  mutate(
    prop_billion = total_prop / 1e9,
    crop_billion = total_crop / 1e9
  )

top_econ %>% select(EVTYPE, prop_billion, crop_billion, total_econ)
## # A tibble: 10 x 4
##    EVTYPE            prop_billion crop_billion    total_econ
##    <chr>                    <dbl>        <dbl>         <dbl>
##  1 FLOOD                   145.       5.66     150319678257 
##  2 HURRICANE/TYPHOON        69.3      2.61      71913712800 
##  3 TORNADO                  56.9      0.415     57362333946.
##  4 STORM SURGE              43.3      0.000005  43323541000 
##  5 HAIL                     15.7      3.03      18761221491.
##  6 FLASH FLOOD              16.8      1.42      18244041078.
##  7 DROUGHT                   1.05    14.0       15018672000 
##  8 HURRICANE                11.9      2.74      14610229010 
##  9 RIVER FLOOD               5.12     5.03      10148404500 
## 10 ICE STORM                 3.94     5.02       8967041360
econ_long <- top_econ %>%
  select(EVTYPE, prop_billion, crop_billion) %>%
  pivot_longer(
    cols = c(prop_billion, crop_billion),
    names_to = "measure",
    values_to = "billions"
  ) %>%
  mutate(
    measure = recode(measure,
      prop_billion = "Property damage",
      crop_billion = "Crop damage"
    ),
    EVTYPE = factor(EVTYPE, levels = rev(top_econ$EVTYPE))
  )

ggplot(econ_long, aes(x = EVTYPE, y = billions, fill = measure)) +
  geom_col(position = "stack") +
  coord_flip() +
  scale_fill_manual(values = c("Property damage" = "#3c2a21", "Crop damage" = "#b5652d")) +
  labs(
    title = "Top 10 Event Types by Economic Impact",
    x = "Event type",
    y = "Total damage (billions of dollars, 1950-2011)",
    fill = NULL
  ) +
  theme_minimal(base_size = 12)

Figure 2. Total property and crop damage (in billions of dollars) by event type, for the ten event types with the highest combined economic impact, 1950-2011.

Figure 2 shows total property damage (dark segment) and crop damage (light segment), stacked to show combined economic impact, for the ten costliest event types. FLOOD produced the largest combined economic damage, at approximately $150.3 billion. Separately, examining crop damage alone shows that DROUGHT is responsible for the single largest crop damage total, reflecting its disproportionate effect on agriculture relative to structural property.

Conclusion

Tornadoes represent the clearest public health risk in the NOAA Storm Database, both in terms of fatalities and injuries, far outpacing any other event type. Economically, water-related events — floods and hurricanes/typhoons — cause the greatest combined damage, primarily through property destruction, while drought stands out specifically as the dominant driver of crop losses. These patterns suggest that public health preparedness resources should prioritize tornado warning systems and shelter infrastructure, while economic mitigation planning (e.g., flood defenses and insurance policy) should prioritize flood- and hurricane-prone regions.

Analysis generated automatically with R version 4.0.0 (2020-04-24) on July 27, 2026.