Synopsis

This report examines the human and economic consequences of severe weather events recorded in the U.S. National Oceanic and Atmospheric Administration (NOAA) Storm Database between 1950 and November 2011. Population-health impacts are assessed separately using the numbers of fatalities and injuries associated with each reported event type. Economic consequences are assessed using estimated property and crop damage, converted into U.S. dollars with the magnitude codes supplied in the original data. Event labels are standardized conservatively to avoid combining substantively different categories. The analysis identifies the event types associated with the largest recorded totals, rather than estimating individual risk or causal effects. Interpretation is limited by evolving reporting practices, inconsistent event labels, approximate damage estimates, and the absence of inflation adjustment.

Data Processing

Loading the original NOAA data

The analysis begins with the original compressed CSV file, downloaded directly from the assignment’s source when it is not already present locally. R reads the .csv.bz2 file directly; no externally preprocessed dataset is used. To make the analysis reproducible, all subsequent cleaning, conversion, aggregation, and visualization are performed in this document.

library(ggplot2)
library(knitr)
knitr::opts_chunk$set(echo=TRUE, message=FALSE, warning=FALSE,
                      fig.align="center")

source_url <- paste0(
  "https://d396qusza40orc.cloudfront.net/",
  "repdata%2Fdata%2FStormData.csv.bz2"
)
data_file <- "StormData.csv.bz2"

if (!file.exists(data_file)) {
  download.file(source_url, destfile=data_file, mode="wb")
}
stopifnot(file.exists(data_file), file.info(data_file)$size > 1000000)

storm_raw <- read.csv(bzfile(data_file), stringsAsFactors=FALSE)
required <- c("EVTYPE", "FATALITIES", "INJURIES", "PROPDMG",
              "PROPDMGEXP", "CROPDMG", "CROPDMGEXP")
stopifnot(all(required %in% names(storm_raw)))

cat("Recorded events:", format(nrow(storm_raw), big.mark=","), "\n")
## Recorded events: 902,297
cat("Variables in source:", ncol(storm_raw), "\n")
## Variables in source: 37

Defining health and economic outcomes

For public health, fatalities and injuries are reported separately: they are distinct outcomes and should not be confused with one another. Their sum is also used as a descriptive indicator of the total number of recorded casualties, not as a measure of severity-weighted burden.

Only formatting inconsistencies in EVTYPE are corrected: surrounding spaces are removed, internal whitespace is reduced, and letters are converted to uppercase. Potentially synonymous but different event categories are not automatically merged, avoiding undocumented reclassification. Consequently, rankings describe event types as reported (after this conservative cleaning).

For economics, the data store a numerical damage amount alongside a magnitude code. K, M, and B mean thousands, millions, and billions of dollars, respectively; H means hundreds. Blank and 0 codes are interpreted as unscaled amounts. Unknown or ambiguous nonzero damage codes are treated as missing instead of assigning them an invented multiplier. The number of such records is reported below, and these uncertain amounts are omitted from monetary totals. Fatalities and injuries from those records remain in the health analysis. These estimates are nominal dollars, not inflation adjusted.

storm <- storm_raw[, required]
rm(storm_raw)

storm$event <- toupper(gsub("[[:space:]]+", " ", trimws(storm$EVTYPE)))
storm$event[is.na(storm$event) | storm$event == ""] <- "UNSPECIFIED"

# NOAA damage multiplier codes. Unrecognized codes are not guessed.
damage_multiplier <- function(code) {
  code <- toupper(trimws(as.character(code)))
  multiplier <- rep(NA_real_, length(code))
  multiplier[!is.na(code) & code %in% c("", "0")] <- 1
  multiplier[!is.na(code) & code == "H"] <- 1e2
  multiplier[!is.na(code) & code == "K"] <- 1e3
  multiplier[!is.na(code) & code == "M"] <- 1e6
  multiplier[!is.na(code) & code == "B"] <- 1e9
  multiplier
}

storm$property_usd <- storm$PROPDMG * damage_multiplier(storm$PROPDMGEXP)
storm$crop_usd <- storm$CROPDMG * damage_multiplier(storm$CROPDMGEXP)

# Only missing or ambiguous positive damage estimates affect reported sums.
unknown_property <- sum(is.na(storm$property_usd) &
                        !is.na(storm$PROPDMG) & storm$PROPDMG > 0)
unknown_crop <- sum(is.na(storm$crop_usd) &
                    !is.na(storm$CROPDMG) & storm$CROPDMG > 0)

quality <- data.frame(
  Indicator=c("Records", "Distinct event labels after formatting",
              "Positive property estimates with ambiguous units",
              "Positive crop estimates with ambiguous units"),
  Value=c(nrow(storm), length(unique(storm$event)),
          unknown_property, unknown_crop)
)
kable(quality, caption="Dataset size and damage-conversion checks")
Dataset size and damage-conversion checks
Indicator Value
Records 902297
Distinct event labels after formatting 883
Positive property estimates with ambiguous units 35
Positive crop estimates with ambiguous units 0

Summarizing outcomes by event type

Totals are calculated over the available records for each event type. Missing values are excluded from sums rather than replaced with assumed damages. The analysis uses aggregate counts and monetary amounts, which are relevant for historical resource planning but should not be interpreted as per-event probabilities or as adjusted measures of future risk.

health <- aggregate(cbind(FATALITIES, INJURIES) ~ event,
                    data=storm,
                    FUN=function(x) sum(x, na.rm=TRUE))
health$casualties <- health$FATALITIES + health$INJURIES

# Convert missing monetary values to zero for the purpose of summing
# the remaining known dollar amounts in each event category.
storm$property_known <- ifelse(is.na(storm$property_usd), 0, storm$property_usd)
storm$crop_known <- ifelse(is.na(storm$crop_usd), 0, storm$crop_usd)

economic <- aggregate(cbind(property_known, crop_known) ~ event,
                      data=storm, FUN=sum)
names(economic)[2:3] <- c("property_usd", "crop_usd")
economic$total_usd <- economic$property_usd + economic$crop_usd

# Reproducibility and quality checks
stopifnot(nrow(storm) > 900000,
          all(health$FATALITIES >= 0), all(health$INJURIES >= 0),
          all(economic$total_usd >= 0),
          !anyNA(economic$total_usd))

Results

Which events were most harmful to population health?

Both fatality and injury totals are analyzed, because the categories with the greatest number of deaths need not be the same as those with the greatest number of injuries. The following table lists the five largest event categories for each outcome.

top_fatal <- head(health[order(-health$FATALITIES),
                         c("event", "FATALITIES")], 5)
top_injury <- head(health[order(-health$INJURIES),
                          c("event", "INJURIES")], 5)
names(top_fatal) <- c("Event type", "Fatalities")
names(top_injury) <- c("Event type", "Injuries")

kable(top_fatal, caption="Five event types with the most reported deaths")
Five event types with the most reported deaths
Event type Fatalities
745 TORNADO 5633
107 EXCESSIVE HEAT 1903
129 FLASH FLOOD 978
234 HEAT 937
407 LIGHTNING 816
kable(top_injury, caption="Five event types with the most reported injuries")
Five event types with the most reported injuries
Event type Injuries
745 TORNADO 91346
766 TSTM WIND 6957
145 FLOOD 6789
107 EXCESSIVE HEAT 6525
407 LIGHTNING 5230

The leading category for recorded fatalities is TORNADO (5,633 deaths). The leading category for recorded injuries is TORNADO (91,346 injuries). These are historical reported totals, not rates adjusted for population exposure.

make_top <- function(column, label, n=10) {
  d <- health[order(-health[[column]]), c("event", column)]
  d <- head(d, n)
  data.frame(event=d$event, count=d[[column]], outcome=label,
             stringsAsFactors=FALSE)
}
health_plot <- rbind(make_top("FATALITIES", "Fatalities"),
                     make_top("INJURIES", "Injuries"))
# Each panel uses its own labels and ranking.
health_plot$category <- paste(health_plot$event, health_plot$outcome, sep="___")
health_plot$category <- reorder(health_plot$category, health_plot$count)

ggplot(health_plot, aes(x=count, y=category, fill=outcome)) +
  geom_col(width=0.72, show.legend=FALSE) +
  facet_wrap(~outcome, scales="free", nrow=1) +
  scale_y_discrete(labels=function(x) sub("___.*$", "", x)) +
  scale_x_continuous(labels=function(x) format(x, big.mark=",", scientific=FALSE)) +
  labs(title="Health impact of severe weather in the United States",
       subtitle="Top 10 recorded event types for each outcome, 1950–2011",
       x="Recorded people affected", y=NULL) +
  theme_minimal(base_size=11) +
  theme(strip.text=element_text(face="bold"),
        panel.grid.major.y=element_blank(),
        plot.title=element_text(face="bold"))
Figure 1. Ten event types with the largest reported fatalities and injuries, displayed as two panels. Bars represent cumulative event counts recorded in the NOAA database during 1950–2011; the x-axis scale is allowed to differ between panels.

Figure 1. Ten event types with the largest reported fatalities and injuries, displayed as two panels. Bars represent cumulative event counts recorded in the NOAA database during 1950–2011; the x-axis scale is allowed to differ between panels.

Which events caused the greatest economic consequences?

Property and crop losses were converted to dollars before aggregation, then added to estimate combined reported economic damage. The table below lists the ten event types associated with the greatest nominal combined losses, expressed in billions of U.S. dollars. As a further check, the largest property-loss and crop-loss categories are displayed separately.

econ_top <- head(economic[order(-economic$total_usd), ], 10)
econ_table <- data.frame(
  `Event type`=econ_top$event,
  `Property (USD bn)`=round(econ_top$property_usd / 1e9, 2),
  `Crops (USD bn)`=round(econ_top$crop_usd / 1e9, 2),
  `Total (USD bn)`=round(econ_top$total_usd / 1e9, 2),
  check.names=FALSE
)
kable(econ_table,
      caption="Ten event types with the greatest combined reported damage")
Ten event types with the greatest combined reported damage
Event type Property (USD bn) Crops (USD bn) Total (USD bn)
FLOOD 144.66 5.66 150.32
HURRICANE/TYPHOON 69.31 2.61 71.91
TORNADO 56.94 0.41 57.35
STORM SURGE 43.32 0.00 43.32
HAIL 15.73 3.03 18.76
FLASH FLOOD 16.14 1.42 17.56
DROUGHT 1.05 13.97 15.02
HURRICANE 11.87 2.74 14.61
RIVER FLOOD 5.12 5.03 10.15
ICE STORM 3.94 5.02 8.97
highest_property <- economic$event[which.max(economic$property_usd)]
highest_crop <- economic$event[which.max(economic$crop_usd)]
cat("Largest property-damage category:", highest_property, "\n")
## Largest property-damage category: FLOOD
cat("Largest crop-damage category:", highest_crop, "\n")
## Largest crop-damage category: DROUGHT

The largest combined nominal economic loss is associated with FLOOD, representing approximately USD 150.32 billion. Property losses are highest for FLOOD, whereas crop losses are highest for DROUGHT. These rankings reflect the reported monetary totals in the historical data and do not adjust for inflation, variations in reporting, or changes in exposed assets.

econ_plot <- econ_top
econ_plot$event <- reorder(econ_plot$event, econ_plot$total_usd)

ggplot(econ_plot, aes(x=total_usd/1e9, y=event)) +
  geom_col(fill="#327F82", width=0.73) +
  scale_x_continuous(labels=function(x) format(x, big.mark=",", trim=TRUE)) +
  labs(title="Economic losses from severe weather in the United States",
       subtitle="Property and crop damage combined, 1950–2011",
       x="Reported damage (billion USD, nominal)", y=NULL) +
  theme_minimal(base_size=12) +
  theme(panel.grid.major.y=element_blank(),
        plot.title=element_text(face="bold"))
Figure 2. The ten NOAA event types with the greatest cumulative reported economic losses (property plus crop damage), in nominal billions of U.S. dollars. Unrecognized damage-magnitude codes are excluded rather than assigned a guessed value.

Figure 2. The ten NOAA event types with the greatest cumulative reported economic losses (property plus crop damage), in nominal billions of U.S. dollars. Unrecognized damage-magnitude codes are excluded rather than assigned a guessed value.

Interpretation and limitations

The two questions reveal different dimensions of weather-event burden: the highest numbers of deaths and injuries are not necessarily associated with the largest monetary losses. The rankings should be interpreted as descriptive comparisons of cumulative reported impacts, not as predictions of expected losses or as measures of risk per event. The NOAA database is less complete in its earlier years, its event classifications have changed over time, and some historical labels are not standardized. Reported damage values are estimates in nominal dollars, and some ambiguous magnitude codes cannot be converted reliably. These limitations should be considered when using the historical findings to understand preparedness priorities.

Data source

National Oceanic and Atmospheric Administration (NOAA), historical Storm Data provided for the Coursera Reproducible Research assignment, 1950–November 2011. NOAA describes its storm records and damage estimates as subject to reporting limitations; the monetary amounts in the database are not adjusted for inflation.