Comparison of the Cost and Casualties of Weather-Related Event Categories

Synopsis

Several decades of NOAA records of weather-related event were compared with respect to monetary damages and casualties. The data were processed to group events by major event category. The primary metrics for comparison were the mean annual damage costs and mean annual casualties. Results indicate that floods and hurricanes or tropical storms (including damages from storm surges) were the most costly weather events. However, tornadoes caused the most casualties, followed by hot weather and floods.

Data Processing

The data for this analysis were obtained from the U.S. National Oceanic and Atmospheric Administration’s (NOAA) storm database at https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2. In this database, the National Weather Service (NWS) and other agencies have documented the occurrrence of storms and other weather phenomena having the potential to cause loss of life, injuries, significant property or crop damage. The version of the database used for this project includes records from 1950 to 2011. However, the records are much more complete from the 1990s and later.

The following code was used to read the data from the raw *.csv file:

noaa_data <- read.csv(here("repdata_data_StormData.csv"))

The following code converts character dates to dates, and creates a new variable YEAR that is the year of each event.

noaa_data$BGN_DATE <- mdy_hms(noaa_data$BGN_DATE)
noaa_data$YEAR <- year(noaa_data$BGN_DATE)

The following codes creates a new variable CASUALTIES that is the sum of the fatalities and injuries of each event.

noaa_data %>%
  mutate(CASUALTIES = rowSums(across(c(FATALITIES, INJURIES)))) -> noaa_data

The following code creates a function to calculate the property and crop damages, applies that function to the database, and then sums the property and crop damages to determine the total monetary damage (TOTDAM) for each event.

calcpd <- function(x,y)   {
  if (x == 0) {z = 0} else
  if (y == "K")  {z = x*1000} else
  if (y == "M" || y == "m") {z = x*1000000} else
  if (y == "B") {z = x*1000000000}
  else {z = NA}
}

noaa_data$PROPDAM <- mapply(calcpd, noaa_data[,25], noaa_data[,26] )
noaa_data$CROPDAM <- mapply(calcpd, noaa_data[,27], noaa_data[,28] )
noaa_data$TOTDAM <- noaa_data$PROPDAM + noaa_data$CROPDAM

The NOAA storm database included a field EVTYPE to identify the type of weather phenomenon. However, this field used many different descriptors even for the same general category of event. Therefore, it was necessary to identify a smaller, manageable number of event categories (EVTYPE2) and group the events accordingly. This was accomplished by the following code. Note that hurricanes, tropical storms, storm surges, and high surf/tides were all included in the “hurricane/tropical” event category because of the impracticality of clearly distinguishing between these event types.

HurricaneEVs <- c("HURRICANE", "STORM SURGE", "SURF", "TIDE", "TYPHOON", "TROPICAL")
TornadoEVs <-c("TORNADO", "FUNNEL", "SPOUT", "DEVIL")
HailEVs <- c("HAIL")
FloodEVs <- c("FLOOD", "FLD")
ColdEVs <- c("COLD", "CHILL", "COOL", "FREEZE", "RECORD LOW", "FROST", "LOW TEMP")
HeatEVs <- c("HEAT", "WARM", "RECORD HIGH", "HIGH TEMP")
ThunderEVs <- c("THUNDER", "TSTM")
FogEVs <- c("FOG")
LightningEVs <- c("LIGHTNING")
WinterEVs <- c("WINT", "SNOW", "ICE", "CHILL", "BLIZZARD", "SLEET", "HEAVY MIX")
FireEVs <- c("FIRE")
DroughtEVs <- c("DROUGHT", "DRY")
WindEVs <- c("WIND")
SlideEVs <- c("SLIDE", "MUD")
AvalancheEVs <- c("AVALANCHE")
RainEVs <- c("RAIN")
TsunamiEVs <- c("TSUNAMI")
noaa_data$EVTYPE2 <- "Other"

for (i in 1:nrow(noaa_data))   {   
   if (grepl(paste(HurricaneEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Hurricane/Tropical"  } else
   
   if (grepl(paste(ThunderEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Thunderstorm"  } else

   if (grepl(paste(LightningEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Lightning"  } else
   
   if (grepl(paste(TornadoEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Tornado"  } else
 
   if (grepl(paste(FloodEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Flood"  } else
   
   if (grepl(paste(FireEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Wildfire"  } else
   
   if (grepl(paste(SlideEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Land/Mud Slide"  } else
   
   if (grepl(paste(AvalancheEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Avalanche"  } else
   
   if (grepl(paste(HeatEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Heat"  }  else
   
   if (grepl(paste(DroughtEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Drought"  }  else
   
   if (grepl(paste(ColdEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Cold"  }  else
   
   if (grepl(paste(HailEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Hail"  } else
      
   if (grepl(paste(FogEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Fog"  } else
   
   if (grepl(paste(WinterEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
            useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Winter Storm"  } else
   
   if (grepl(paste(WindEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Other Wind"  } else
   
   if (grepl(paste(RainEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Other Rain"  } else
               
   if (grepl(paste(TsunamiEVs, collapse='|'), noaa_data[i,8], ignore.case = TRUE,
             useBytes = TRUE) == TRUE)  {noaa_data[i,43] = "Tsunami"  } else
               
             {noaa_data[i,43] = "Other"}         
}

The final step in data processing was to calculate the sum of total damage and total casualties by each event type by year, and calculate the mean of the annual sums for each event category. The processed data are stored in a data frame called “Final Data”.

dam_ann_sum <- tapply(noaa_data$TOTDAM, list(noaa_data$YEAR, noaa_data$EVTYPE2), sum)
caus_ann_sum <- tapply(noaa_data$CASUALTIES, list(noaa_data$YEAR, noaa_data$EVTYPE2), sum)
Mean_Ann_Dam <- t(data.frame(as.list(colMeans(dam_ann_sum, na.rm = TRUE))))
Mean_Ann_Caus <- t(data.frame(as.list(colMeans(caus_ann_sum,na.rm = TRUE))))
colnames(Mean_Ann_Dam)[1] <- "Mean_Annual_Dam"
Final_Data <- cbind(Mean_Ann_Dam, Mean_Ann_Caus[,1])
colnames(Final_Data)[2] <- "Mean_Annual_Casualties"
Final_Data <- cbind(rownames(Final_Data), data.frame(Final_Data, row.names=NULL))
colnames(Final_Data)[1] <- "EVTYPE2"

Results

Table 1 presents the means of the total annual damage (in $) and total annual casualties by event type. The mean annual damage and mean annual casualties are plotted in Figure 1 and 2, respectively. Results indicate that floods and hurricanes or tropical storms (including damages from storm surges) were the most costly weather events. However, tornadoes caused the most casualties, followed by hot weather and floods.

Table 1 - Mean Annual Monetary Damage and Casualties by Event Type
EVTYPE2 Mean_Annual_Dam Mean_Annual_Casualties
Avalanche 4.590421e+05 20.79
Cold 1.948637e+08 42.37
Drought 7.908116e+08 1.89
Flood 1.043484e+10 538.74
Fog 1.316395e+06 60.84
Hail 3.165196e+08 24.32
Heat 4.867395e+07 653.74
Hurricane.Tropical 8.181322e+09 126.11
Land.Mud.Slide 1.926906e+07 5.50
Lightning 4.687347e+07 318.32
Other 8.429382e+06 102.21
Other.Rain 2.118494e+08 21.58
Other.Wind 3.897129e+08 123.05
Thunderstorm 1.654897e+08 180.72
Tornado 9.407645e+08 1566.50
Tsunami 3.602050e+07 40.50
Wildfire 4.684163e+08 89.37
Winter.Storm 7.205782e+08 353.74
Figure 1. Mean annual monetary damages by event type

Figure 1. Mean annual monetary damages by event type

Figure 2. Mean annual casualties by event type

Figure 2. Mean annual casualties by event type