Synopsis

This analysis examines severe weather events recorded in the U.S. National Oceanic and Atmospheric Administration Storm Database. The main objectives are to identify which event types are most harmful to population health and which have the greatest economic consequences. Population health impact is evaluated using reported fatalities and injuries. Economic impact is assessed using reported property and crop damage. The analysis begins with the original compressed NOAA storm data file and performs all processing within this reproducible R Markdown document. Event types are summarized across the United States to identify those associated with the greatest health and economic impacts.

Data Processing

The NOAA Storm Database was loaded directly from the original compressed .csv.bz2 file. All data cleaning and transformations used in this analysis are performed within this document so that the results can be reproduced from the raw data.

# Set global chunk options
knitr::opts_chunk$set(
  echo = TRUE,
  message = FALSE,
  warning = FALSE
)
# Load the raw NOAA storm data
storm <- read.csv(
  "repdata_data_StormData .csv.bz2",
  stringsAsFactors = FALSE
)

# Check the dimensions of the dataset
dim(storm)
## [1] 902297     37
# Display the first few observations
head(storm)
##   STATE__           BGN_DATE BGN_TIME TIME_ZONE COUNTY COUNTYNAME STATE  EVTYPE
## 1       1  4/18/1950 0:00:00     0130       CST     97     MOBILE    AL TORNADO
## 2       1  4/18/1950 0:00:00     0145       CST      3    BALDWIN    AL TORNADO
## 3       1  2/20/1951 0:00:00     1600       CST     57    FAYETTE    AL TORNADO
## 4       1   6/8/1951 0:00:00     0900       CST     89    MADISON    AL TORNADO
## 5       1 11/15/1951 0:00:00     1500       CST     43    CULLMAN    AL TORNADO
## 6       1 11/15/1951 0:00:00     2000       CST     77 LAUDERDALE    AL TORNADO
##   BGN_RANGE BGN_AZI BGN_LOCATI END_DATE END_TIME COUNTY_END COUNTYENDN
## 1         0                                               0         NA
## 2         0                                               0         NA
## 3         0                                               0         NA
## 4         0                                               0         NA
## 5         0                                               0         NA
## 6         0                                               0         NA
##   END_RANGE END_AZI END_LOCATI LENGTH WIDTH F MAG FATALITIES INJURIES PROPDMG
## 1         0                      14.0   100 3   0          0       15    25.0
## 2         0                       2.0   150 2   0          0        0     2.5
## 3         0                       0.1   123 2   0          0        2    25.0
## 4         0                       0.0   100 2   0          0        2     2.5
## 5         0                       0.0   150 2   0          0        2     2.5
## 6         0                       1.5   177 2   0          0        6     2.5
##   PROPDMGEXP CROPDMG CROPDMGEXP WFO STATEOFFIC ZONENAMES LATITUDE LONGITUDE
## 1          K       0                                         3040      8812
## 2          K       0                                         3042      8755
## 3          K       0                                         3340      8742
## 4          K       0                                         3458      8626
## 5          K       0                                         3412      8642
## 6          K       0                                         3450      8748
##   LATITUDE_E LONGITUDE_ REMARKS REFNUM
## 1       3051       8806              1
## 2          0          0              2
## 3          0          0              3
## 4          0          0              4
## 5          0          0              5
## 6          0          0              6
# Examine the structure of the dataset
str(storm)
## 'data.frame':    902297 obs. of  37 variables:
##  $ STATE__   : num  1 1 1 1 1 1 1 1 1 1 ...
##  $ 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" ...
##  $ BGN_TIME  : chr  "0130" "0145" "1600" "0900" ...
##  $ TIME_ZONE : chr  "CST" "CST" "CST" "CST" ...
##  $ COUNTY    : num  97 3 57 89 43 77 9 123 125 57 ...
##  $ COUNTYNAME: chr  "MOBILE" "BALDWIN" "FAYETTE" "MADISON" ...
##  $ STATE     : chr  "AL" "AL" "AL" "AL" ...
##  $ EVTYPE    : chr  "TORNADO" "TORNADO" "TORNADO" "TORNADO" ...
##  $ BGN_RANGE : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ BGN_AZI   : chr  "" "" "" "" ...
##  $ BGN_LOCATI: chr  "" "" "" "" ...
##  $ END_DATE  : chr  "" "" "" "" ...
##  $ END_TIME  : chr  "" "" "" "" ...
##  $ COUNTY_END: num  0 0 0 0 0 0 0 0 0 0 ...
##  $ COUNTYENDN: logi  NA NA NA NA NA NA ...
##  $ END_RANGE : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ END_AZI   : chr  "" "" "" "" ...
##  $ END_LOCATI: chr  "" "" "" "" ...
##  $ LENGTH    : num  14 2 0.1 0 0 1.5 1.5 0 3.3 2.3 ...
##  $ WIDTH     : num  100 150 123 100 150 177 33 33 100 100 ...
##  $ F         : int  3 2 2 2 2 2 2 1 3 3 ...
##  $ MAG       : num  0 0 0 0 0 0 0 0 0 0 ...
##  $ 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  "" "" "" "" ...
##  $ WFO       : chr  "" "" "" "" ...
##  $ STATEOFFIC: chr  "" "" "" "" ...
##  $ ZONENAMES : chr  "" "" "" "" ...
##  $ LATITUDE  : num  3040 3042 3340 3458 3412 ...
##  $ LONGITUDE : num  8812 8755 8742 8626 8642 ...
##  $ LATITUDE_E: num  3051 0 0 0 0 ...
##  $ LONGITUDE_: num  8806 0 0 0 0 ...
##  $ REMARKS   : chr  "" "" "" "" ...
##  $ REFNUM    : num  1 2 3 4 5 6 7 8 9 10 ...
# Display the variable names
names(storm)
##  [1] "STATE__"    "BGN_DATE"   "BGN_TIME"   "TIME_ZONE"  "COUNTY"    
##  [6] "COUNTYNAME" "STATE"      "EVTYPE"     "BGN_RANGE"  "BGN_AZI"   
## [11] "BGN_LOCATI" "END_DATE"   "END_TIME"   "COUNTY_END" "COUNTYENDN"
## [16] "END_RANGE"  "END_AZI"    "END_LOCATI" "LENGTH"     "WIDTH"     
## [21] "F"          "MAG"        "FATALITIES" "INJURIES"   "PROPDMG"   
## [26] "PROPDMGEXP" "CROPDMG"    "CROPDMGEXP" "WFO"        "STATEOFFIC"
## [31] "ZONENAMES"  "LATITUDE"   "LONGITUDE"  "LATITUDE_E" "LONGITUDE_"
## [36] "REMARKS"    "REFNUM"

Only the variables required for the population health and economic impact analyses were retained. EVTYPE identifies the type of weather event. FATALITIES and INJURIES measure population health impacts. PROPDMG and PROPDMGEXP describe property damage, while CROPDMG and CROPDMGEXP describe crop damage.

# Retain only variables needed for the analysis
storm_analysis <- storm[, c(
  "EVTYPE",
  "FATALITIES",
  "INJURIES",
  "PROPDMG",
  "PROPDMGEXP",
  "CROPDMG",
  "CROPDMGEXP"
)]

# Display the first few observations
head(storm_analysis)
##    EVTYPE FATALITIES INJURIES PROPDMG PROPDMGEXP CROPDMG CROPDMGEXP
## 1 TORNADO          0       15    25.0          K       0           
## 2 TORNADO          0        0     2.5          K       0           
## 3 TORNADO          0        2    25.0          K       0           
## 4 TORNADO          0        2     2.5          K       0           
## 5 TORNADO          0        2     2.5          K       0           
## 6 TORNADO          0        6     2.5          K       0

The event type labels were standardized by converting them to uppercase and removing leading or trailing spaces. This reduces simple formatting differences while preserving the original event classifications.

# Standardize event type labels
storm_analysis$EVTYPE <- toupper(
  trimws(storm_analysis$EVTYPE)
)

# Count the number of unique event labels
length(unique(storm_analysis$EVTYPE))
## [1] 890

After basic standardization, 890 unique event labels remain. This reflects historical inconsistencies and variations in NOAA event naming. Extensive manual recoding is avoided so that the transformations remain transparent and reproducible.

Economic damage in the NOAA Storm Database is recorded using a numeric damage amount together with an exponent code. For example, K represents thousands, M represents millions, and B represents billions. These exponent codes must be converted to numeric multipliers before property and crop damage can be compared across events.

# Examine the exponent codes used for property damage
unique(storm_analysis$PROPDMGEXP)
##  [1] "K" "M" ""  "B" "m" "+" "0" "5" "6" "?" "4" "2" "3" "h" "7" "H" "-" "1" "8"
# Examine the exponent codes used for crop damage
unique(storm_analysis$CROPDMGEXP)
## [1] ""  "M" "K" "m" "B" "?" "0" "k" "2"

The exponent variables contain standard codes as well as some historical or nonstandard values. In this analysis, H, K, M, and B are interpreted as hundreds, thousands, millions, and billions. Single numeric codes are treated as powers of 10. Blank or unrecognized symbols are assigned a multiplier of 1 so that the recorded damage value is retained without additional scaling.

# Convert exponent codes to uppercase character values
prop_exp <- toupper(trimws(as.character(storm_analysis$PROPDMGEXP)))
crop_exp <- toupper(trimws(as.character(storm_analysis$CROPDMGEXP)))

# Begin with a multiplier of 1 for every observation
storm_analysis$PROP_MULT <- rep(1, nrow(storm_analysis))
storm_analysis$CROP_MULT <- rep(1, nrow(storm_analysis))

# Assign standard property damage multipliers
storm_analysis$PROP_MULT[prop_exp == "H"] <- 1e2
storm_analysis$PROP_MULT[prop_exp == "K"] <- 1e3
storm_analysis$PROP_MULT[prop_exp == "M"] <- 1e6
storm_analysis$PROP_MULT[prop_exp == "B"] <- 1e9

# Assign standard crop damage multipliers
storm_analysis$CROP_MULT[crop_exp == "H"] <- 1e2
storm_analysis$CROP_MULT[crop_exp == "K"] <- 1e3
storm_analysis$CROP_MULT[crop_exp == "M"] <- 1e6
storm_analysis$CROP_MULT[crop_exp == "B"] <- 1e9

# Handle numeric exponent codes from 0 through 8
for (i in 0:8) {
  storm_analysis$PROP_MULT[prop_exp == as.character(i)] <- 10^i
  storm_analysis$CROP_MULT[crop_exp == as.character(i)] <- 10^i
}

# Confirm that the multiplier variables have the correct length
length(storm_analysis$PROP_MULT)
## [1] 902297
length(storm_analysis$CROP_MULT)
## [1] 902297
nrow(storm_analysis)
## [1] 902297

The three values above should be identical. This confirms that every row in the dataset has a property and crop damage multiplier.

# Confirm the multiplier vectors match the number of rows
stopifnot(
  length(storm_analysis$PROP_MULT) == nrow(storm_analysis),
  length(storm_analysis$CROP_MULT) == nrow(storm_analysis)
)

# Calculate property damage in dollars
storm_analysis$PROPERTY_DAMAGE <-
  storm_analysis$PROPDMG * storm_analysis$PROP_MULT

# Calculate crop damage in dollars
storm_analysis$CROP_DAMAGE <-
  storm_analysis$CROPDMG * storm_analysis$CROP_MULT

# Calculate total economic damage
storm_analysis$TOTAL_DAMAGE <-
  storm_analysis$PROPERTY_DAMAGE +
  storm_analysis$CROP_DAMAGE

# Inspect the newly created damage variables
head(
  storm_analysis[, c(
    "PROPDMG",
    "PROPDMGEXP",
    "PROPERTY_DAMAGE",
    "CROPDMG",
    "CROPDMGEXP",
    "CROP_DAMAGE",
    "TOTAL_DAMAGE"
  )]
)
##   PROPDMG PROPDMGEXP PROPERTY_DAMAGE CROPDMG CROPDMGEXP CROP_DAMAGE
## 1    25.0          K           25000       0                      0
## 2     2.5          K            2500       0                      0
## 3    25.0          K           25000       0                      0
## 4     2.5          K            2500       0                      0
## 5     2.5          K            2500       0                      0
## 6     2.5          K            2500       0                      0
##   TOTAL_DAMAGE
## 1        25000
## 2         2500
## 3        25000
## 4         2500
## 5         2500
## 6         2500

Property and crop damage were converted to dollar values using the corresponding multipliers. Total economic damage was then calculated as the sum of property and crop damage for each observation.

Results

Population Health Impact

Population health impact was evaluated using the total number of reported fatalities and injuries associated with each event type. A combined health impact measure was calculated by adding fatalities and injuries for each event category.

# Calculate total fatalities and injuries by event type
health_summary <- aggregate(
  cbind(FATALITIES, INJURIES) ~ EVTYPE,
  data = storm_analysis,
  FUN = sum,
  na.rm = TRUE
)

# Calculate combined health impact
health_summary$TOTAL_HEALTH_IMPACT <-
  health_summary$FATALITIES +
  health_summary$INJURIES

# Sort event types from greatest to smallest health impact
health_summary <- health_summary[
  order(-health_summary$TOTAL_HEALTH_IMPACT),
]

# Display the ten event types with the greatest health impact
head(health_summary, 10)
##                EVTYPE FATALITIES INJURIES TOTAL_HEALTH_IMPACT
## 750           TORNADO       5633    91346               96979
## 108    EXCESSIVE HEAT       1903     6525                8428
## 771         TSTM WIND        504     6957                7461
## 146             FLOOD        470     6789                7259
## 410         LIGHTNING        816     5230                6046
## 235              HEAT        937     2100                3037
## 130       FLASH FLOOD        978     1777                2755
## 379         ICE STORM         89     1975                2064
## 677 THUNDERSTORM WIND        133     1488                1621
## 880      WINTER STORM        206     1321                1527
# Select the top ten event types
top_health <- head(health_summary, 10)

# Create a matrix for fatalities and injuries
health_matrix <- rbind(
  Fatalities = top_health$FATALITIES,
  Injuries = top_health$INJURIES
)

# Create stacked bar plot
barplot(
  health_matrix,
  names.arg = top_health$EVTYPE,
  las = 2,
  cex.names = 0.7,
  ylab = "Number of People Affected",
  main = "Severe Weather Events with the Greatest Health Impact",
  legend.text = TRUE
)
Figure 1. Top 10 severe weather event types by reported fatalities and injuries in the United States.

Figure 1. Top 10 severe weather event types by reported fatalities and injuries in the United States.

Tornadoes produced the greatest overall population health impact, with 5,633 fatalities and 91,346 injuries, for a combined total of 96,979 reported deaths and injuries. Excessive heat ranked second, followed by TSTM wind, flood, and lightning. These results show that tornadoes were associated with substantially greater reported human harm than the other individual event categories in the database.

The event labels should be interpreted with some caution because historical variations in NOAA event classifications remain in the dataset. For example, TSTM WIND and THUNDERSTORM WIND appear as separate event categories.

Economic Consequences

Economic consequences were evaluated using the estimated dollar value of property and crop damage associated with each event type. Property and crop damage were combined to obtain the total economic impact for each event category.

# Calculate total economic damage by event type
economic_summary <- aggregate(
  TOTAL_DAMAGE ~ EVTYPE,
  data = storm_analysis,
  FUN = sum,
  na.rm = TRUE
)

# Sort event types from greatest to smallest economic damage
economic_summary <- economic_summary[
  order(-economic_summary$TOTAL_DAMAGE),
]

# Display the ten event types with the greatest economic damage
head(economic_summary, 10)
##                EVTYPE TOTAL_DAMAGE
## 146             FLOOD 150319678257
## 364 HURRICANE/TYPHOON  71913712800
## 750           TORNADO  57362333946
## 591       STORM SURGE  43323541000
## 204              HAIL  18761221986
## 130       FLASH FLOOD  18244041078
## 76            DROUGHT  15018672000
## 355         HURRICANE  14610229010
## 521       RIVER FLOOD  10148404500
## 379         ICE STORM   8967041360
# Summarize property and crop damage separately by event type
economic_components <- aggregate(
  cbind(PROPERTY_DAMAGE, CROP_DAMAGE) ~ EVTYPE,
  data = storm_analysis,
  FUN = sum,
  na.rm = TRUE
)

# Calculate total economic damage
economic_components$TOTAL_DAMAGE <-
  economic_components$PROPERTY_DAMAGE +
  economic_components$CROP_DAMAGE

# Sort from greatest to smallest total economic damage
economic_components <- economic_components[
  order(-economic_components$TOTAL_DAMAGE),
]

# Display the top ten event types
head(economic_components, 10)
##                EVTYPE PROPERTY_DAMAGE CROP_DAMAGE TOTAL_DAMAGE
## 146             FLOOD    144657709807  5661968450 150319678257
## 364 HURRICANE/TYPHOON     69305840000  2607872800  71913712800
## 750           TORNADO     56947380676   414953270  57362333946
## 591       STORM SURGE     43323536000        5000  43323541000
## 204              HAIL     15735267513  3025954473  18761221986
## 130       FLASH FLOOD     16822723978  1421317100  18244041078
## 76            DROUGHT      1046106000 13972566000  15018672000
## 355         HURRICANE     11868319010  2741910000  14610229010
## 521       RIVER FLOOD      5118945500  5029459000  10148404500
## 379         ICE STORM      3944927860  5022113500   8967041360
# Select the ten event types with the greatest economic damage
top_economic <- head(economic_summary, 10)

# Convert total damage to billions of dollars
top_economic$DAMAGE_BILLIONS <-
  top_economic$TOTAL_DAMAGE / 1e9

# Create bar plot
barplot(
  top_economic$DAMAGE_BILLIONS,
  names.arg = top_economic$EVTYPE,
  las = 2,
  cex.names = 0.7,
  ylab = "Total Damage (Billions of Dollars)",
  main = "Severe Weather Events with the Greatest Economic Impact"
)
Figure 2. Top 10 severe weather event types by total estimated property and crop damage in the United States.

Figure 2. Top 10 severe weather event types by total estimated property and crop damage in the United States.

# Summarize property and crop damage separately by event type
economic_components <- aggregate(
  cbind(PROPERTY_DAMAGE, CROP_DAMAGE) ~ EVTYPE,
  data = storm_analysis,
  FUN = sum,
  na.rm = TRUE
)

# Calculate total economic damage
economic_components$TOTAL_DAMAGE <-
  economic_components$PROPERTY_DAMAGE +
  economic_components$CROP_DAMAGE

# Sort by total economic damage
economic_components <- economic_components[
  order(economic_components$TOTAL_DAMAGE, decreasing = TRUE),
]

# Display top ten
head(economic_components, 10)
##                EVTYPE PROPERTY_DAMAGE CROP_DAMAGE TOTAL_DAMAGE
## 146             FLOOD    144657709807  5661968450 150319678257
## 364 HURRICANE/TYPHOON     69305840000  2607872800  71913712800
## 750           TORNADO     56947380676   414953270  57362333946
## 591       STORM SURGE     43323536000        5000  43323541000
## 204              HAIL     15735267513  3025954473  18761221986
## 130       FLASH FLOOD     16822723978  1421317100  18244041078
## 76            DROUGHT      1046106000 13972566000  15018672000
## 355         HURRICANE     11868319010  2741910000  14610229010
## 521       RIVER FLOOD      5118945500  5029459000  10148404500
## 379         ICE STORM      3944927860  5022113500   8967041360

Floods produced the greatest overall economic impact, with approximately $149.83 billion in combined property and crop damage. Most of this loss came from property damage, which accounted for about $144.66 billion, while crop damage contributed approximately $5.17 billion.

Hurricane/Typhoon events ranked second with about $71.91 billion in total damage, followed by tornadoes with approximately $57.35 billion and storm surge events with about $43.32 billion. Flash floods and hail were also among the event types associated with major economic losses.

For most of the highest-ranking event types, property damage was the dominant source of economic loss. However, some categories such as river flood and ice storm showed a larger contribution from crop damage relative to other events.

These findings show that the weather events associated with the greatest economic consequences are not identical to those associated with the greatest population health impacts. Tornadoes produced the largest combined health impact, while floods produced the greatest total economic damage.

Conclusion

The NOAA Storm Database shows that severe weather events differ substantially in their effects on population health and the economy. Tornadoes produced the greatest combined number of reported fatalities and injuries, making them the most harmful event type with respect to population health in this analysis. Excessive heat, thunderstorm wind, floods, and lightning were also important contributors to human health impacts.

In terms of economic consequences, floods produced the largest total estimated damage, with approximately $149.83 billion in combined property and crop losses. Hurricane/Typhoon events, tornadoes, and storm surge events were also associated with substantial economic damage.

Overall, the results show that the event types responsible for the greatest human health impacts are not necessarily the same as those responsible for the greatest economic losses. The analysis also highlights that most of the economic impact among the highest-ranking events was driven by property damage, although crop losses were important for some event categories.