Economic and Public Health Impact of Different Severe Weather Events in the United States

Carl Lee McKinney

Synopsis

Storms and other severe weather events can have significant public health and economic impact on local communities and municipalities by causing fatalities, injuries, and property damage. Preventing or mitigating such outcomes is a key concern that can shape public policy decisions. Knowing the extent of the impact of different types of events can inform these decisions.

The U.S. National Oceanic and Atmospheric Administration (NOAA) maintains a storm database that tracks characteristics of major storms and weather events in the United States, including type of event, when and where they occur, and also estimates of any fatalities, injuries, and damages to property and crops. Analysis of this data can reveal which types of events have had the most significant economic and public health impact.

Data Processing

For this report, we will analyze cached storm data gathered between 1950 and 2011 using R.

## Download data into local directory and load into dataframe
if(!file.exists("./storm")){dir.create("./storm")}
setwd("./storm")
fileUrl<-"https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2"
download.file(fileUrl,destfile="./StormData.csv.bz2",method="curl")
stormData<-read.csv("StormData.csv.bz2")

As this analysis will look at data for the entire period of time and across all locations in the dataset, variables dealing with time and location are unnecessary. These are filtered out, as are other unnnecessary variables such as ‘REMARKS’, in order to reduce processing time.

library(dplyr)
stormData<-stormData%>%select(EVTYPE,FATALITIES,INJURIES,PROPDMG,PROPDMGEXP,CROPDMG,CROPDMGEXP)

The National Weather Service presides over the collection of this storm data. While NWSI 10-1605 stipulates a list of 48 event names under which storm events permitted in the storm data must be categorized, the EVTYPE (event type) factor variable in the dataset has 985 levels. A cursory look at these levels reveals duplications due to mispelling (e.g. ‘AVALANCE’,‘AVALANCHE’), case sensitivity (e.g. ‘frost’, ‘FROST’), and appended suffixes (e.g. ‘COASTAL FLOODING’, ‘COASTAL FLOOD’); mixing of types (e.g. ‘BLIZZARD AND EXTREME WIND CHILL’), presumed misnaming of types (e.g. ‘BEACH EROSION’ is likely due to ‘COASTAL FLOOD’ or ‘HIGH SURF’), miscategorization (e.g. ‘APACHE COUNTY’), unpermitted events (‘COOL SPELL’), and some entries that are the effects of events rather than events themselves (e.g. ‘DROWNING’ or ‘HYPOTHERMIA’). Clearly the data needs significant cleaning in order to get an accurate assessment of the impact of different events. Events are relabeled to fit in a permitted category with which they can be identified, while those that cannot be so fit are labeled as ‘OTHER’. Some of the 48 stipulated event names are also combined for simplicity (e.g. ‘High Wind’, ‘Marine High Wind’, ‘Marine Strong Wind’ into ‘WIND’). The result is 30 types of events coded in factor variable EVTYPE.

## Series of gsubs to combine types
stormData$EVTYPE<-gsub(".*AVALANCE.*","AVALANCHE",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*beach.*|.*coastal.*flood.*|.*coastal.*erosion.*|.*cstl.*|.*high tide.*|.*out tide.*|^tidal flood.*|^coastal surge$","COASTAL FLOOD",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*blizzard.*","BLIZZARD",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*wind chill.*|.*cold.*|.*low temperature.*|.*cool.*|.*record.|*low.*","COLD/WIND CHILL",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*drought.*|.*dry.*|below normal precipitation|driest month","DROUGHT",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*dust.*|.*smoke.*|.*vog.*|.*volcanic.*","DUST/ASH/SMOKE",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*fire.*","FIRE",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub("^flood.*|^flash.*|^lake.*flood$|.*floood.*|.*water.*|.*fld.*|.*flash.*|^highway flood.*|^major flood.*|^minor flood.*|^river flood.*|^street flood.*|^breakup flood.*|^local flood.*|^rural flood.*","FLOOD",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*fog.*","FOG",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*funnel.*|.*gustnado.*","FUNNEL CLOUD",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*frost.*|.*freeze.*|.*freezing.*","HAIL",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*hail.*","HAIL",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*heat.*|.*hot.*|.*temperature.*|.*warm.*|.*record.*high.*","HEAT",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*high.*surf.*|*high.*swells.*|.*high.*seas.*|.*high.*waves.*|.*heavy.*surf.*|.*heavy.*swells.*|.*heavy.*seas.*|.*hazardous.*surf.*|.*rough.*seas|.*rough.*surf.*|.*storm.*surge.*","HIGH SURF",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*hurricane.*|.*typhoon.*|.*floyd.*","HURRICANE",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*ice.*|.*glaze.*|.*icy.*","ICE",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*lighting.*|.*ligntning.*|.*lightning.*","LIGHTNING",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*rain.*|.*microburst.*|.*precipitation.*|.*precipatation.*|.*precip.*|.*shower.*|.*downburst.*|.*coastal.*storm.*|.*wet.*","RAIN",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*sleet.*","SLEET",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*slide.*|.*slump.*","SLIDE",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*snow.*","SNOW",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*thunderstorm.*","THUNDERSTORM",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*tornado.*|torndau","TORNADO",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*wind.*|.*tstm.*|wnd","WIND",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*waterspout.*|wayterspout","WATERSPOUT",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*winter.*|.*wintry.*","WINTER STORM/WEATHER",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*summary.*","SUMMARY",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub(".*tropical.*","TROPICAL STORM",stormData$EVTYPE,ignore.case=TRUE)
stormData$EVTYPE<-gsub("\\?|dam break|heavy mix|.*exposure.*|.*hypothermia.*|.*wall cloud|marine.*|.*metro storm.*|no severe weather|northern lights|red flag criteria|severe turbulence|.*stream.*|southeast|.*urban.*|apache.*|dam.*|drowning|excessive|^high$|mild.*|none|other|rogue wave|summary|landspout","OTHER",stormData$EVTYPE,ignore.case=TRUE)

## Coerce EVTYPE back to factor
stormData$EVTYPE<-as.factor(stormData$EVTYPE)

The impact on public health can be measured by looking at the number of INJURIES and FATALITIES attributed to different events. Reshaping the data allows these variables to be examined together.

## Gather variable INJURIES and FATALITIES
library(tidyr)
stormData<-gather(stormData,PH,PHvalue,c(INJURIES,FATALITIES))

Economic impact can be measured by the estimated damage in dollars to property and crops attributed to different events. Once again, reshaping the data allows these variables to be examined together.

## Convert PROPDMGEXP and CROPDMGEXP to numeric multipliers
stormData$PROPDMGEXP<-gsub("h","100",stormData$PROPDMGEXP,ignore.case=TRUE)
stormData$PROPDMGEXP<-gsub("k","1000",stormData$PROPDMGEXP,ignore.case=TRUE)
stormData$PROPDMGEXP<-gsub("m","1000000",stormData$PROPDMGEXP,ignore.case=TRUE)
stormData$PROPDMGEXP<-gsub("b","1000000000",stormData$PROPDMGEXP,ignore.case=TRUE)
stormData$PROPDMGEXP<-gsub("^$|-|\\+|\\?|^0$|2|3|4|5|6|7|8","1",stormData$PROPDMGEXP,ignore.case=TRUE)
stormData$CROPDMGEXP<-gsub("h","100",stormData$CROPDMGEXP,ignore.case=TRUE)
stormData$CROPDMGEXP<-gsub("k","1000",stormData$CROPDMGEXP,ignore.case=TRUE)
stormData$CROPDMGEXP<-gsub("m","1000000",stormData$CROPDMGEXP,ignore.case=TRUE)
stormData$CROPDMGEXP<-gsub("b","1000000000",stormData$CROPDMGEXP,ignore.case=TRUE)
stormData$CROPDMGEXP<-gsub("^$|-|\\+|\\?|^0$|2|3|4|5|6|7|8","1",stormData$CROPDMGEXP,ignore.case=TRUE)
stormData$PROPDMGEXP<-as.numeric(stormData$PROPDMGEXP)
stormData$CROPDMGEXP<-as.numeric(stormData$CROPDMGEXP)

## Recast PROPDM as multiplier of PROPDMGEXP and CROPDMG as mutliplier of CROPDMGEXP
stormData$PROPDMG<-stormData$PROPDMG*stormData$PROPDMGEXP/1000000
stormData$CROPDMG<-stormData$CROPDMG*stormData$CROPDMGEXP/1000000

## Gather variables PROPDMG and CROPDMG
stormData<-gather(stormData,DAMAGE,DAMAGEvalue,c(PROPDMG,CROPDMG))

Results

The impact of storms and severe weather on public health can be examined by plotting injuries and fatalities attributed to different types of events.

library(ggplot2)
injFat<-ggplot(stormData, aes(EVTYPE,PHvalue,fill=PH))
      injFat<-injFat+theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5))
      injFat<-injFat+labs(title="U.S. Injuries and Fatalities by Severe Weather Event, 1950-2011",x="Event Type",y="",fill="")
      injFat+geom_bar(stat="identity")

Clearly the largest number of injuries and fatalities are attributed to tornados; heat, wind, and flood events are in a distant 2nd, 3rd, and 4th position. Table 1 below shows the actual numbers for these events.

library(knitr)
inj<-stormData%>%
  filter(PH=="INJURIES")%>%
  group_by(EVTYPE)%>%
  summarize(Injuries=sum(PHvalue))%>%
  arrange(desc(Injuries))%>%
  top_n(4)
fat<-stormData%>%
  filter(PH=="FATALITIES")%>%
  group_by(EVTYPE)%>%
  summarize(Fatalities=sum(PHvalue))%>%
  arrange(desc(Fatalities))%>%
  top_n(4)
injFatTable<-inner_join(inj,fat)
kable(injFatTable,col.names=c("Event Type","Injuries","Fatalities"),format.args=list(big.mark=","),caption="Table 1. Top Public Health Impact of Severe Weather Events")
Table 1. Top Public Health Impact of Severe Weather Events
Event Type Injuries Fatalities
TORNADO 182,728 11,266
HEAT 18,456 6,286
WIND 18,388 2,866
FLOOD 17,494 3,112

The economic impact of storms and severe weather can be examined by plotting the estimated damages to property and crops attributed to different types of events.

options(scipen=999) ## Turn off scientific notation
damage<-ggplot(stormData, aes(EVTYPE,DAMAGEvalue,fill=DAMAGE))
      damage<-damage+theme(axis.text.x=element_text(angle=90,hjust=1,vjust=0.5))
      damage<-damage+labs(title="U.S. Economic Damage by Severe Weather Event, 1950-2011",x="Event Type",y="Dollars (millions)",fill="")
      damage+geom_bar(stat="identity")

The most extensive economic impact as measured by damage to property and crops is atrributed to floods, although damage attributed to hurricanes, tornados, high surf, and hail is also substantial. It should also be noted that the highest amount of crop damage is attributed to drought, though very little property damage is attributed to this event. These numbers are in Table 2 below.

prop<-stormData%>%
  filter(DAMAGE=="PROPDMG")%>%
  group_by(EVTYPE)%>%
  summarize(Property=sum(DAMAGEvalue*1000000))
crop<-stormData%>%
  filter(DAMAGE=="CROPDMG")%>%
  group_by(EVTYPE)%>%
  summarize(Crop=sum(DAMAGEvalue)*1000000)
types<-c("FLOOD","HURRICANE","TORNADO","HIGH SURF","HAIL","DROUGHT")
propCropTable<-inner_join(prop,crop)%>%
  filter(EVTYPE%in%types)%>%
  arrange(desc(Property))
kable(propCropTable,col.names=c("Event Type","Property Damage ($)","Crop Damage ($)"),format.args=list(big.mark=","),caption="Table 2. Top Economic Impact of Severe Weather Events")
Table 2. Top Economic Impact of Severe Weather Events
Event Type Property Damage ($) Crop Damage ($)
FLOOD 334,315,507,143 24,763,686,400
HURRICANE 170,712,820,020 11,032,235,600
TORNADO 113,883,863,957 829,922,940
HIGH SURF 96,160,569,000 4,710,000
HAIL 35,311,328,133 10,222,547,746
DROUGHT 2,106,077,200 27,945,273,560

This simple analysis suggests that tornados, hurricanes, and floods should be the focus of policy work seeking to alleviate the impact of severe weather events. However, given the localized nature of these events and the differntial impact they have on property, crops, and human lives, a more extensive and complex analysis is needed to determine the implementation of policies enacting more targeted interventions at community and municipality levels.