Synopsis

This report analyzes the U.S. National Oceanic and Atmospheric Administration (NOAA) Storm Database (raw CSV.bz2) to answer two questions: (1) which types of events are most harmful to population health (fatalities + injuries), and (2) which event types have the greatest economic consequences (property + crop damage). The analysis begins from the raw compressed CSV file, performs necessary data cleaning and unit conversion for damage exponents, and aggregates impacts by EVTYPE. Results are presented with reproducible R code (using dplyr and ggplot2) and two figures: a top-10 event types by health impact and a top-10 by economic impact. All code chunks show their source (echo = TRUE) so the work is reproducible. The document includes a Data Processing section describing transformations and a Results section with figures and interpretation.

Data Processing

This section loads the raw data, documents assumptions and transformations, and prepares the summary tables used in the Results.

knitr::opts_chunk$set(echo = TRUE, message = TRUE, warning = TRUE)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
library(readr)

Download and read raw data

The analysis starts from the original compressed CSV file provided for the assignment. If you already have the file locally, set local_file accordingly. The default below downloads from the course URL (the standard link used in the Coursera assignment site).

# URL used in the original assignment (standard location for the Coursera assignment)
url <- "https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2"
local_file <- "StormData.csv.bz2"

if (!file.exists(local_file)) {
  download.file(url, destfile = local_file, mode = "wb")
}

# read directly from the bzip2 compressed file
storms <- read.csv(local_file, stringsAsFactors = FALSE)

# quick peek
dim(storms)
## [1] 902297     37
str(storms[c("EVTYPE", "FATALITIES", "INJURIES", "PROPDMG", "PROPDMGEXP", "CROPDMG", "CROPDMGEXP")])
## 'data.frame':    902297 obs. of  7 variables:
##  $ 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  "" "" "" "" ...

Notes on variables and transformations

  • EVTYPE is the event type (character). Many entries use inconsistent capitalization or spelling; for a first-pass analysis we will use simple standardization (trim, upper-case) and then aggregate by the cleaned EVTYPE values. A more thorough analysis could manually collapse similar event names into canonical categories.
  • FATALITIES and INJURIES are numeric counts and can be summed directly.
  • PROPDMG and CROPDMG represent numeric amounts with multipliers indicated in PROPDMGEXP / CROPDMGEXP. The exponent field contains characters like K, M, B, numeric digits, or other symbols. We convert these to multipliers and compute total dollar damages.
# helper: convert exponent code to multiplier
exp_to_mult <- function(e) {
  e <- toupper(trimws(e))
  e[e == ""] <- ""
  sapply(e, function(x) {
    if (x %in% c("H")) return(100)
    if (x %in% c("K")) return(1e3)
    if (x %in% c("M")) return(1e6)
    if (x %in% c("B")) return(1e9)
    # sometimes numeric characters "0"-"9" indicate power of ten
    if (grepl("^[0-9]+$", x)) return(10^as.numeric(x))
    # + or - or ? or other characters: treat as multiplier 1 (conservative)
    return(1)
  })
}

storms <- storms %>%
  mutate(
    EVTYPE_CLEAN = toupper(trimws(EVTYPE)),
    PROPDMGEXP_CLEAN = toupper(trimws(PROPDMGEXP)),
    CROPDMGEXP_CLEAN = toupper(trimws(CROPDMGEXP))
  )

# compute multiplier and dollar damage
storms <- storms %>%
  mutate(
    prop_mult = exp_to_mult(PROPDMGEXP_CLEAN),
    crop_mult = exp_to_mult(CROPDMGEXP_CLEAN),
    PROPDMG_USD = as.numeric(PROPDMG) * prop_mult,
    CROPDMG_USD = as.numeric(CROPDMG) * crop_mult,
    HEALTH_IMPACT = as.numeric(FATALITIES) + as.numeric(INJURIES),
    ECONOMIC_IMPACT = PROPDMG_USD + CROPDMG_USD
  )

# quick sanity checks
summary(storms$PROPDMG_USD)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 0.000e+00 0.000e+00 0.000e+00 4.746e+05 5.000e+02 1.150e+11
summary(storms$CROPDMG_USD)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 0.000e+00 0.000e+00 0.000e+00 5.442e+04 0.000e+00 5.000e+09

Aggregation strategy

  • For population health: sum FATALITIES + INJURIES per EVTYPE_CLEAN.
  • For economic impact: sum PROPDMG_USD + CROPDMG_USD per EVTYPE_CLEAN.
  • We’ll present the top 10 event types for each metric.
health_by_event <- storms %>%
  group_by(EVTYPE_CLEAN) %>%
  summarise(
    total_fatalities = sum(FATALITIES, na.rm = TRUE),
    total_injuries = sum(INJURIES, na.rm = TRUE),
    total_health = sum(HEALTH_IMPACT, na.rm = TRUE),
    n_events = n()
  ) %>%
  arrange(desc(total_health))
## `summarise()` ungrouping output (override with `.groups` argument)
econ_by_event <- storms %>%
  group_by(EVTYPE_CLEAN) %>%
  summarise(
    total_prop = sum(PROPDMG_USD, na.rm = TRUE),
    total_crop = sum(CROPDMG_USD, na.rm = TRUE),
    total_econ = sum(ECONOMIC_IMPACT, na.rm = TRUE),
    n_events = n()
  ) %>%
  arrange(desc(total_econ))
## `summarise()` ungrouping output (override with `.groups` argument)
# top 10
top10_health <- head(health_by_event, 10)
top10_econ <- head(econ_by_event, 10)

knitr::kable(top10_health, caption = "Top 10 event types by combined injuries+fatalities")
Top 10 event types by combined injuries+fatalities
EVTYPE_CLEAN total_fatalities total_injuries total_health n_events
TORNADO 5633 91346 96979 60652
EXCESSIVE HEAT 1903 6525 8428 1678
TSTM WIND 504 6957 7461 219946
FLOOD 470 6789 7259 25327
LIGHTNING 816 5230 6046 15755
HEAT 937 2100 3037 767
FLASH FLOOD 978 1777 2755 54278
ICE STORM 89 1975 2064 2006
THUNDERSTORM WIND 133 1488 1621 82564
WINTER STORM 206 1321 1527 11433
knitr::kable(top10_econ, caption = "Top 10 event types by combined property+crop damage (USD)")
Top 10 event types by combined property+crop damage (USD)
EVTYPE_CLEAN total_prop total_crop total_econ n_events
FLOOD 144657709807 5661968450 150319678257 25327
HURRICANE/TYPHOON 69305840000 2607872800 71913712800 88
TORNADO 56947380676 414953270 57362333946 60652
STORM SURGE 43323536000 5000 43323541000 261
HAIL 15735267513 3025954473 18761221986 288661
FLASH FLOOD 16822723978 1421317100 18244041078 54278
DROUGHT 1046106000 13972566000 15018672000 2488
HURRICANE 11868319010 2741910000 14610229010 174
RIVER FLOOD 5118945500 5029459000 10148404500 173
ICE STORM 3944927860 5022113500 8967041360 2006

Results

This section presents the plots and interprets findings. Figures are limited to two (health and economic), which keeps within the assignment limit of at most three figures.

Figure 1 — Which events are most harmful to population health?

# prepare data for plotting
plot_health <- top10_health %>%
  mutate(EVTYPE_CLEAN = reorder(EVTYPE_CLEAN, total_health))

ggplot(plot_health, aes(x = EVTYPE_CLEAN, y = total_health)) +
  geom_col() +
  coord_flip() +
  labs(x = "Event type", y = "Total fatalities + injuries",
       title = "Top 10 NOAA Event Types by Health Impact") +
  theme_minimal()
Top 10 event types by total fatalities+injuries (descending).

Top 10 event types by total fatalities+injuries (descending).

Caption: This bar chart shows the top 10 event types ranked by combined fatalities and injuries recorded in the NOAA Storm Database (1950–2011). Interpretation notes: event naming in the raw data is inconsistent; some categories (e.g., variations of thunderstorms, hail, wind) may be split across multiple EVTYPE strings and require manual cleaning for final policy use.

Figure 2 — Which events have the greatest economic consequences?

plot_econ <- top10_econ %>%
  mutate(EVTYPE_CLEAN = reorder(EVTYPE_CLEAN, total_econ))

# plot with log scale to manage wide range of damages
ggplot(plot_econ, aes(x = EVTYPE_CLEAN, y = total_econ)) +
  geom_col() +
  coord_flip() +
  scale_y_continuous(labels = scales::dollar_format(prefix = "$", scale = 1, big.mark = ",")) +
  labs(x = "Event type", y = "Total damage (USD)",
       title = "Top 10 NOAA Event Types by Economic Impact (Property + Crop)") +
  theme_minimal()
Top 10 event types by economic damage (property + crop), in US dollars.

Top 10 event types by economic damage (property + crop), in US dollars.

Caption: The bar chart uses absolute USD to show total property and crop damage by event type. Note that damage amounts span several orders of magnitude; for deeper analysis consider plotting on a log scale or presenting median per-event damage.

Interpretation and Limitations

Reproducibility

All code shown above starts from the raw StormData.csv.bz2 file and uses open R packages only. To reproduce the figures and tables, open this R Markdown document in RStudio and knit it to HTML (it will download the raw file automatically if not present).

Appendix — Full code listing

(The full code is shown inline in the document; all chunks have echo = TRUE.)


End of report.