Synopsis: This analysis explores the NOAA Storm Database and aims to identify the most severe weather events both in terms of injuries, fatalities and the economic damage caused across the United States. The raw ‘EVTYPE’ field contains many inconsistent and overlapping labels which were cleaned and consolidated in to eight categories: Tornado, Flood, Thunderstorm Wind, Lightning, Precipitation, Wind and a composite group called Extreme Weather Events- the consolidation was done by pattern matching on standardised weather descriptions. Marine and Land-based thunderstorm wind events were kept separate, since these may have different practical implications. Economic damage was determined by converting the property and crop damage magnitude and exponent fields in to actual dollar values. Results show that Tornadoes are by far the leading cause of both fatalities and injuries exceeding all other categories. However, when it comes to economic impact this changes and flooding tends to cause the greatest total damage narrowly. But it takes only a narrow lead over the broader Extreme Weather Events category, with Tornadoes and Precipitation-related events (such as rain or hail) following behind. These findings suggest tornado preparedness should be prioritized for protecting public health, while flood mitigation infrastructure offers the greatest potential for the reduction of economic losses.

Load the required libraries

library(ggplot2)
library(reshape2)

Data Processing

The raw data was obtained from the NOAA Storm Data-base, it was downloaded programatically (using the ‘download.file()’ function) in order to ensure reproducibility and loaded into R using the read.csv function. The dataset contains 902,397 storm event records and 37 variables.

Loading the data

download.file('https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2', method = 'curl', destfile = 'repdata_data_StormData.csv.bz2')

sddata <- read.csv('repdata_data_StormData.csv.bz2')

Here, the ‘EVTYPE’ field was converted into upper-case for easy analysis and all whitespaces were trimmed Processing the data

sddata$EVTYPE <- toupper(sddata$EVTYPE) # Convert the 'EVTYPE' column of data-set to uppercase

sddata$EVTYPE <- gsub(" ", "", sddata$EVTYPE) # Trim all white-spaces

# Initialize the 'EVENT_CATEGORY' column
sddata$EVENT_CATEGORY <- NA

The EVTYPE variable, which records the type of weather event contained inconsistent, misspelled labels (‘TSTMWIND’,‘THUNDERSTORMWINDS’ and ‘THUNDERSTORMWIND’) all describing the same phenomenon. This problem was addressed by converting EVTYPE to uppercase and trimming all white-spaces, which were then consolidated into a smaller set of standardized categories using pattern matching. Events were classified in order into: Thunderstorm Wind, Marine Thunderstorm Wind, Lightning, Tornado, Flood, Precipitation, and a broad category called Extreme Weather Event, and Wind (remaining non-thunderstorm-related). Any event not matching one of these patterns was into a residual ‘Other’ category. This categorization scheme groups events primarily by the underlying phenomenon, with location used where the documentation treats it as a meaningfully distinct event type. Classify the events into categories

sddata$EVENT_CATEGORY[grepl('THUNDERSTORM|TSTM', sddata$EVTYPE) & !grepl("MARINE", sddata$EVTYPE)] <- "Thunderstorm Wind"
sddata$EVENT_CATEGORY[grepl('THUNDERSTORM|TSTM', sddata$EVTYPE) & grepl("MARINE", sddata$EVTYPE)] <- "Marine Thunderstorm Wind"
sddata$EVENT_CATEGORY[sddata$EVTYPE == "LIGHTNING"] <- "Lightning"
sddata$EVENT_CATEGORY[sddata$EVTYPE == "TORNADO"] <- "Tornado"

sddata$EVENT_CATEGORY[grepl("FLOOD", sddata$EVTYPE) & is.na(sddata$EVENT_CATEGORY)] <- "Flood"

sddata$EVENT_CATEGORY[grepl('HAIL|RAIN|SNOW|SLEET', sddata$EVTYPE) & is.na(sddata$EVENT_CATEGORY)] <- 'Precipitation'
sddata$EVENT_CATEGORY[grepl("HURRICANE|TYPHOON|TROPICALSTORM|TROPICALDEPRESSION|BLIZZARD|ICESTORM|WINTERSTORM|EXTREMEHEAT|EXCESSIVEHEAT|EXTREMECOLD|DROUGHT|WILDFIRE|FIRE", sddata$EVTYPE) & is.na(sddata$EVENT_CATEGORY)] <- "Extreme Weather Events"
sddata$EVENT_CATEGORY[grepl("WIND", sddata$EVTYPE) & is.na(sddata$EVENT_CATEGORY)] <- "Wind"
sddata$EVENT_CATEGORY[is.na(sddata$EVENT_CATEGORY)] <- "Other"

To assess the economic impact of the above events, the ‘PROPDMGEXP’ and the ‘CROPDMGEXP’ fields, which encode a multiplier for the corresponding damage magnitude fields were standardized to uppercase and mapped to their numeric multipliers. A smaller number of rows contained undocumented or ambiguous exponent codes, these represented well under one percent of the data-set and were treated conservatively. Property and crop damage were each multiplied by their respective standardized components and summed to produce a total economic damage figure for each event

# Clean and standardize EXP codes
sddata$PROPDMGEXP <- toupper(trimws(sddata$PROPDMGEXP))
sddata$CROPDMGEXP <- toupper(trimws(sddata$CROPDMGEXP))

# Property damage multiplier
sddata$PROP_MULT <- 1
sddata$PROP_MULT[sddata$PROPDMGEXP == "H"] <- 1e2
sddata$PROP_MULT[sddata$PROPDMGEXP == "K"] <- 1e3
sddata$PROP_MULT[sddata$PROPDMGEXP == "M"] <- 1e6
sddata$PROP_MULT[sddata$PROPDMGEXP == "B"] <- 1e9
digit_rows_prop <- grepl("^[0-8]$", sddata$PROPDMGEXP)
sddata$PROP_MULT[digit_rows_prop] <- 10^as.numeric(sddata$PROPDMGEXP[digit_rows_prop])
sddata$PROP_MULT[!(sddata$PROPDMGEXP %in% c("", "H","K","M","B","0","1","2","3","4","5","6","7","8"))] <- 0

sddata$PROP_DAMAGE <- sddata$PROPDMG * sddata$PROP_MULT

# Crop damage multiplier
sddata$CROP_MULT <- 1
sddata$CROP_MULT[sddata$CROPDMGEXP == "H"] <- 1e2
sddata$CROP_MULT[sddata$CROPDMGEXP == "K"] <- 1e3
sddata$CROP_MULT[sddata$CROPDMGEXP == "M"] <- 1e6
sddata$CROP_MULT[sddata$CROPDMGEXP == "B"] <- 1e9
digit_rows_crop <- grepl("^[0-8]$", sddata$CROPDMGEXP)
sddata$CROP_MULT[digit_rows_crop] <- 10^as.numeric(sddata$CROPDMGEXP[digit_rows_crop])
sddata$CROP_MULT[!(sddata$CROPDMGEXP %in% c("", "H","K","M","B","0","1","2","3","4","5","6","7","8"))] <- 0

sddata$CROP_DAMAGE <- sddata$CROPDMG * sddata$CROP_MULT

# Total economic damage
sddata$TOTAL_DAMAGE <- sddata$PROP_DAMAGE + sddata$CROP_DAMAGE

Results

##Population Health Impact Figure 1 shows total fatalities and injuries aggregated by event category, sorted from most to least harmful. Tornadoes are responsible for the highest number of both fatalities (5,633) and injuries (91,346) by a substantial margin — more than double the fatalities of the next-highest category, the broader Extreme Weather Events group (3,008 fatalities), and over six times the injury count of the next-closest category. Flood, Thunderstorm Wind, and Lightning follow as the next most significant contributors to fatalities, while injury patterns show a similar ordering. These results indicate that tornado preparedness and early-warning systems represent the highest-priority investment for reducing loss of life and injury from severe weather.

Aggregation of fatalities and injuries by category

health_agg <-aggregate(cbind(FATALITIES, INJURIES) ~ EVENT_CATEGORY, data = sddata, sum)
health_agg[order(-health_agg$FATALITIES),]
##             EVENT_CATEGORY FATALITIES INJURIES
## 8                  Tornado       5633    91346
## 1   Extreme Weather Events       3007    14426
## 5                    Other       2552     6626
## 2                    Flood       1525     8604
## 3                Lightning        816     5230
## 7        Thunderstorm Wind        735     9510
## 9                     Wind        564     1912
## 6            Precipitation        294     2840
## 4 Marine Thunderstorm Wind         19       34

Aggregation of Total Economic Damage by category

damage_agg <-aggregate(TOTAL_DAMAGE ~ EVENT_CATEGORY, data = sddata, sum)
damage_agg[order(-damage_agg$TOTAL_DAMAGE),]
##             EVENT_CATEGORY TOTAL_DAMAGE
## 2                    Flood 180591769913
## 1   Extreme Weather Events 141622474931
## 8                  Tornado  57362333886
## 5                    Other  51546650430
## 6            Precipitation  24238825976
## 7        Thunderstorm Wind  14053055288
## 9                     Wind   6965571473
## 3                Lightning    942471520
## 4 Marine Thunderstorm Wind      5907400

For plotting we will use the ggplot2 library Figure 1 Population Health Impact

health_long <- melt(health_agg, id.vars = "EVENT_CATEGORY",
                    measure.vars = c("FATALITIES", "INJURIES"),
                    variable.name = "Metric", value.name = "Count")

ggplot(health_long, aes(x = reorder(EVENT_CATEGORY, -Count), y=Count, fill= Metric)) +
    geom_bar(stat = "identity") + 
    facet_wrap(~ Metric, scales = "free_y") + 
    theme_minimal() +
    theme(axis.text = element_text(angle = 45, hjust = 1)) +
    labs(title = "Population Health Impact by Event category",
         x="Event Category" , y = "Count") + 
    scale_fill_manual(values = c("FATALITIES" = "firebrick", "INJURIES" = "orange"))

Figure 2 Economic Damage

Figure 2 shows total economic damage (property and crop damage combined) by event category, in billions of dollars. Flood events caused the greatest total damage (approximately $180.4 billion), narrowly ahead of the composite Extreme Weather Events category (approximately $141.7 billion), followed by Tornado ($57.4 billion) and the residual ‘Other’ category ($51.7 billion). Precipitation-related events (hail, rain, snow) and Thunderstorm Wind caused comparatively smaller but still notable damage. These findings suggest that flood mitigation and drainage infrastructure investment offers the greatest potential return in reducing future economic losses from severe weather, complementing the population-health case for tornado-focused preparedness.

ggplot(damage_agg, aes(x = reorder(EVENT_CATEGORY, -TOTAL_DAMAGE), y = TOTAL_DAMAGE/1e9)) +
    geom_bar(stat = "identity", fill = "steelblue") + 
    theme_minimal() +
    theme(axis.text = element_text(angle = 45, hjust = 1)) +
    labs(title = "Total Economic Damage by Event Category",
         x="Event Category" , y = "Damage (Billions USD)")