Synopsis

The objective of this analysis was to determine which types of storm events in the United States have been the most harmful to population health and which types have had the greatest economic consequences. The data included storm events from 2007 through 2011 taken from the NOAA Storm Event Database. The 10 most harmful and 10 most damaging storming events will be reported, and the states experiencing the largest impact from each of these event lists will be identified. The data were processed using R version 3.2.1 (2015-06-18).

The most harmful storm event was the tornado, producing in excess of 10,000 fatalities and injuries during this 5-year period. The most damaging storm event in terms of economic impact was flooding, result in over $15 billion of damage, followed closely by tornadoes.The states with the largest number of harmful events were Alabama and Missouri, while the state suffering the most economic damage was Texas.

Data Processing

The data used for this analysis were taken from the United States National Oceanic and Atmospheric Administration’s (NOAA) Storm Event Database. This database has been used since 1950 to record data about major storms and weather events in the U.S, such as date, location, magnitude, and estimates of fatalities, injuries, and property damage which are related to the event. There are some limitations to this database:

The data were processed using R version 3.2.1 (2015-06-18) on a x86_64-w64-mingw32 system. Several additional packages were used to tidy the raw data and prepare the report.

library(dplyr)
## 
## Attaching package: 'dplyr'
## 
## The following object is masked from 'package:stats':
## 
##     filter
## 
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(lubridate)
library(stringr)
library(ggplot2)
library(maps)
library(grid)
library(gridExtra)
library(pander)
library(RColorBrewer)
panderOptions('knitr.auto.asis', TRUE)
panderOptions('round', 1)
panderOptions('table.style', 'multiline')
panderOptions('table.split.table', Inf)
panderOptions('list.style', 'ordered')
all_state <- map_data("state")
states <- state.abb
dc <- data.frame(abb = "DC", region = "district of columbia")
states.dc <- data.frame(abb = state.abb, region = str_to_lower(state.name[match(states, state.abb)])) %>%
    bind_rows(dc)
## Warning in rbind_all(list(x, ...)): Unequal factor levels: coercing to
## character
## Warning in rbind_all(list(x, ...)): Unequal factor levels: coercing to
## character
noaa.events <- read.csv("noaa event types.csv", colClasses = "character") %>%
    mutate(event.type = str_to_title(event.type))

NOAA Storm Event Types

pandoc.list(as.list(noaa.events$event.type))
  1. Astronomical Low Tide
  2. Avalanche
  3. Blizzard
  4. Coastal Flood
  5. Cold/Wind Chill
  6. Debris Flow
  7. Dense Fog
  8. Dense Smoke
  9. Drought
  10. Dust Devil
  11. Dust Storm
  12. Excessive Heat
  13. Extreme Cold/Wind Chill
  14. Flash Flood
  15. Flood
  16. Frost/Freeze
  17. Funnel Cloud
  18. Freezing Fog
  19. Hail
  20. Heat
  21. Heavy Rain
  22. Heavy Snow
  23. High Surf
  24. High Wind
  25. Hurricane (Typhoon)
  26. Ice Storm
  27. Lake-Effect Snow
  28. Lakeshore Flood
  29. Lightning
  30. Marine Hail
  31. Marine High Wind
  32. Marine Strong Wind
  33. Marine Thunderstorm Wind
  34. Rip Current
  35. Seiche
  36. Sleet
  37. Storm Surge/Tide
  38. Strong Wind
  39. Thunderstorm Wind
  40. Tornado
  41. Tropical Depression
  42. Tropical Storm
  43. Tsunami
  44. Volcanic Ash
  45. Waterspout
  46. Wildfire
  47. Winter Storm
  48. Winter Weather
raw <- read.csv("repdata-data-StormData.csv.bz2", colClasses = "character") 

Scope of the Analysis

The analysis was limited to events which occurred between 2007 and 2011. This date range was selected because the data during this period followed stricter NOAA specifications for categorizing storm events, resulting in significantly fewer inconsistencies than earlier time periods. Furthermore, historical data was limited to selected storm event types (e.g., only tornado, thunderstorm wind, and hail were reported from 1955 to 1992), which could bias the results towards these events.

Tidying the Data

Initial processing of the raw data began by assigning variables to the proper classes. The data were limited to events occurring on or after January 1, 2007. The full state names were added to the data set, which will be used to map the prevalence of events on a state-by-state basis.

data <- transmute(raw, begin.date = mdy_hms(BGN_DATE),
                  end.date = mdy_hms(END_DATE),
                  state = STATE,
                  county = COUNTYNAME,
                  event = str_to_title(str_trim(EVTYPE, side = "both")),
                  tornado.strength = as.numeric(F),
                  magnitude = as.numeric(MAG),
                  fatalities = as.numeric(FATALITIES),
                  injuries = as.numeric(INJURIES),
                  property = as.numeric(PROPDMG),
                  pde = ifelse(PROPDMGEXP == "", NA, str_to_lower(PROPDMGEXP)),
                  crop = as.numeric(CROPDMG),
                  cde = ifelse(CROPDMGEXP == "", NA, str_to_lower(CROPDMGEXP))) %>%
    filter(begin.date >= mdy("1/1/2007")) %>%
    left_join(states.dc, by=c("state" = "abb")) 

To evaluate property and crop damage, the numerical damage figure was multiplied by the exponent to calculate the actual amount of damage. The following definitions were used for the exponents:

  • h = hundreds
  • k = thousands
  • m = millions
  • b = billions

For any other character in the exponent, the damage value was multiplied by 10.

  • This was determined by cross-referencing damage values with the online NOAA Storm Event Database, which indicated that these miscellaneous characters were erroneously placed in the damage exponent column when in fact they should have been the last digit of the damage value. Since these values were very small, the damage value was rounded to the approximate value through multiplying by 10.
data <- mutate(data, pde = str_replace(pde, "([^bhkm])", 10),
              pde = str_replace(pde, "h", 100),
              pde = str_replace(pde, "k", 1000),
              pde = str_replace(pde, "m", 1000000),
              pde = str_replace(pde, "b", 1000000000),
              pde = as.numeric(pde),
              property.damage = ifelse(!is.na(pde), property * pde, property),
              cde = str_replace(cde, "([^bhkm])", 10),
              cde = str_replace(cde, "h", 100),
              cde = str_replace(cde, "k", 1000),
              cde = str_replace(cde, "m", 1000000),
              cde = str_replace(cde, "b", 1000000000),
              cde = as.numeric(cde),
              crop.damage = ifelse(!is.na(cde), crop * cde, crop))

Summarizing the Data

To summarize the data, the total number of fatalities, injuries, property damage, and crop damage for each storm event were calculated. The total harm of the event was then determined by adding the number of fatalities and injuries. The total damage produced by the event was determine by adding the amount of property damage with the amount of crop damage.

events.total <- group_by(data, event) %>%
    summarize(count = n(),
              fatalities = sum(fatalities),
              injuries = sum(injuries),
              property.damage = sum(property.damage),
              crop.damage = sum(crop.damage)) %>%
    mutate(harm = fatalities + injuries,
           damage = property.damage + crop.damage)

Results

Events included in this analysis occurred between 2007 and 2011. In this analysis, harmful to the population health was defined as causing a fatality or injury, while economic consequence was defined as causing damage to property or crops.

The Most Harmful and Most Damaging Storm Event Types

The total harm and damage were calculated for each event type, and the top 10 events in each group were selected. The total amount of damge will be reported as $Billions. The 10 most harmful event types and 10 most damaging event types are reported in figure 1 below.

A full list of results for all 48 storm event types can be found in table 1 in the appendix at the end of this document.

top.harm <- select(events.total, event, harm) %>%
    arrange(desc(harm)) %>%
    top_n(10, harm)

top.damage <- select(events.total, event, damage) %>%
    mutate(damage = damage / 1000000000) %>%
    arrange(desc(damage)) %>%
    top_n(10, damage)
cols <- brewer.pal(5, "Blues")
graph1 <- ggplot(top.harm, aes(x=event, y=harm)) +
    geom_bar(stat="identity", fill=cols[3], color="black") + 
    ggtitle("A. Most Harmful Storm Events") +
    xlab("Storm Event") +
    ylab("Number of Harmful Events") +
    scale_x_discrete(limits=top.harm$event) +
    theme_bw() +
    theme(axis.text.x = element_text(angle=30, hjust=1, vjust=1))

cols <- brewer.pal(5, "Greens")
graph2 <- ggplot(top.damage, aes(x=event, y=damage)) +
    geom_bar(stat="identity", fill=cols[3], color="black") + 
    ggtitle("B. Most Damaging Storm Events") +
    xlab("Storm Event") +
    ylab("Damage Totals in Billions ($)") +
    scale_x_discrete(limits=top.damage$event) +
    theme_bw() +
    theme(axis.text.x = element_text(angle=30, hjust=1, vjust=1))

grid.arrange(graph1, graph2, ncol=2, main="Figure 1. Top 10 Most Harmful and Most Damaging Events from 2007 to 2011")

States with the Highest Prevelance of Harmful and Damaging Storm Events

The 10 most harmful and 10 most damaging storm event types were then totaled on a state-by-state basis to determine the prevalence of each event type within the 50 U.S. states and District of Columbia. The incidence of these event types, ranging from least to most, can be found in figure 2 below.

state.harm <- filter(data, event %in% top.harm$event) %>%
    group_by(region) %>%
    summarize(count = n(),
          fatalities = sum(fatalities),
          injuries = sum(injuries)) %>%
    mutate(harm = fatalities + injuries) %>%
    arrange(harm) %>%
    inner_join(all_state, by="region")

state.damage <- filter(data, event %in% top.damage$event) %>%
    group_by(region) %>%
    summarize(count = n(),
              property.damage = sum(property.damage),
              crop.damage = sum(crop.damage)) %>%
    mutate(damage = (property.damage + crop.damage)/1000000000) %>%
    arrange(damage) %>%
    inner_join(all_state, by="region")
cols <- brewer.pal(5, "Blues")
graph1 <- ggplot() +
    geom_polygon(data=state.harm, aes(x=long, y=lat, group=group, fill=harm), colour="white") +
    scale_fill_continuous(low=cols[1], high=cols[5], guide="colorbar") +
    labs(title="A. Most Harmful Events", x="", y="", fill="Number of Harmful Events") +
    scale_x_continuous(breaks = NULL) +
    scale_y_continuous(breaks = NULL) +
    theme_bw() +
    theme(legend.position="bottom")

cols <- brewer.pal(5, "Greens")
graph2 <- ggplot() +
    geom_polygon(data=state.damage, aes(x=long, y=lat, group=group, fill=damage), colour="white") +
    scale_fill_continuous(low=cols[1], high=cols[5], guide="colorbar") +
    labs(title="B. Most Damaging Events", x="", y="", fill="Cost of Damaging Events\nin $Billion") +
    scale_x_continuous(breaks = NULL) +
    scale_y_continuous(breaks = NULL) +
    theme_bw() +
    theme(legend.position="bottom")

grid.arrange(graph1, graph2, ncol=2, main="Figure 2. Top 10 Most Harmful and Most Damaging Events by State")

References

  1. NOAA Storm Event Database Details
  2. NOAA’s NWS Documentation

Appendix

all.harm <- select(events.total, event, harm) %>%
    arrange(desc(harm)) 

all.damage <- select(events.total, event, damage) %>%
    mutate(damage = damage / 1000000000) %>%
    arrange(desc(damage)) 

all.harm <- bind_cols(all.harm, all.damage)

colnames(all.harm) <- c("Harmful Events","Harm Produced","Damaging Events","Damage Produced")
set.caption("Table 1. List of Harm and Damage Produced by Storm Events")
pander(all.harm)
Table 1. List of Harm and Damage Produced by Storm Events
Harmful Events Harm Produced Damaging Events Damage Produced
Tornado 10471 Flood 16.9
Thunderstorm Wind 1521 Tornado 14.7
Lightning 1082 Hail 7
Excessive Heat 999 Flash Flood 5.8
Heat 884 Storm Surge/Tide 4.6
Flash Flood 609 Thunderstorm Wind 3.8
Wildfire 455 Hurricane 2.6
Winter Weather 354 Wildfire 2.2
Rip Current 334 High Wind 1.3
Flood 332 Frost/Freeze 0.9
Strong Wind 184 Winter Storm 0.9
Hail 182 Ice Storm 0.8
High Surf 177 Tropical Storm 0.4
High Wind 163 Drought 0.4
Tsunami 162 Lightning 0.3
Avalanche 138 Coastal Flood 0.2
Cold/Wind Chill 105 Heavy Rain 0.1
Winter Storm 55 Landslide 0.1
Extreme Cold/Wind Chill 53 Tsunami 0.1
Heavy Rain 52 High Surf 0.1
Heavy Snow 44 Heavy Snow 0.1
Marine Thunderstorm Wind 35 Strong Wind 0.1
Marine Strong Wind 34 Winter Weather 0
Dust Devil 26 Blizzard 0
Tropical Storm 21 Lake-Effect Snow 0
Ice Storm 17 Lakeshore Flood 0
Landslide 16 Extreme Cold/Wind Chill 0
Storm Surge/Tide 16 Waterspout 0
Hurricane 15 Dust Storm 0
Dust Storm 11 Dense Fog 0
Blizzard 8 Cold/Wind Chill 0
Coastal Flood 4 Avalanche 0
Dense Fog 3 Freezing Fog 0
Marine High Wind 2 Heat 0
Astronomical Low Tide 0 Tropical Depression 0
Dense Smoke 0 Excessive Heat 0
Drought 0 Marine High Wind 0
Freezing Fog 0 Marine Thunderstorm Wind 0
Frost/Freeze 0 Marine Strong Wind 0
Funnel Cloud 0 Dust Devil 0
Lake-Effect Snow 0 Astronomical Low Tide 0
Lakeshore Flood 0 Dense Smoke 0
Marine Hail 0 Seiche 0
Seiche 0 Funnel Cloud 0
Sleet 0 Marine Hail 0
Tropical Depression 0 Rip Current 0
Volcanic Ashfall 0 Sleet 0
Waterspout 0 Volcanic Ashfall 0