Synopsis

This is an assignment for the online Johns Hopkins Reproducible Research course. The basic goal of this assignment is to explore the NOAA Storm Database and to answer two questions:
1. Across the United States, which types of events are most harmful with respect to population health?
2. Across the United States, which types of events have the greatest economic consequences?

More documentation about the database is available from National Weather Service Storm Data Documentation and National Climatic Data Center Storm Events FAQ

Data processing

The first step is to download the data and read the data into the R environment.

## Download the dataset and unzip
if(!file.exists("repdata_data_StormData.csv.bz2")){
        dataURL = "https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2"
        download.file(
                url = dataURL,
                destfile = "repdata_data_StormData.csv.bz2",
                method = "libcurl")}

## Read the storm data
StormData <- read.csv("repdata_data_StormData.csv.bz2")

We will also want to already load some of the dependencies that will be used for data processing and data visualisation in the later steps.

library(dplyr)
library(ggplot2)
library(forcats)
library(cowplot)

Let’s have a little exploratory look at some information about the data set.

names(StormData)
##  [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"
head(StormData,2)
##   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
##   BGN_RANGE BGN_AZI BGN_LOCATI END_DATE END_TIME COUNTY_END COUNTYENDN
## 1         0                                               0         NA
## 2         0                                               0         NA
##   END_RANGE END_AZI END_LOCATI LENGTH WIDTH F MAG FATALITIES INJURIES PROPDMG
## 1         0                        14   100 3   0          0       15    25.0
## 2         0                         2   150 2   0          0        0     2.5
##   PROPDMGEXP CROPDMG CROPDMGEXP WFO STATEOFFIC ZONENAMES LATITUDE LONGITUDE
## 1          K       0                                         3040      8812
## 2          K       0                                         3042      8755
##   LATITUDE_E LONGITUDE_ REMARKS REFNUM
## 1       3051       8806              1
## 2          0          0              2
length(unique(StormData$EVTYPE))
## [1] 985
head(unique(StormData$EVTYPE),10)
##  [1] "TORNADO"                   "TSTM WIND"                
##  [3] "HAIL"                      "FREEZING RAIN"            
##  [5] "SNOW"                      "ICE STORM/FLASH FLOOD"    
##  [7] "SNOW/ICE"                  "WINTER STORM"             
##  [9] "HURRICANE OPAL/HIGH WINDS" "THUNDERSTORM WINDS"

That is interesting!

Firstly, there are a few variables that I’m interested in (such as fatalities, injuries and property damage for example), but also a lot of variables that I’m not going to explore to answer my questions.

Hence let’s only select the variables I’m going to explore to answer my questions and save them in a new dataframe. This will make it easier to work with.

Storm_HealthEconomic_Data <- select(StormData, EVTYPE,
                            FATALITIES,INJURIES,
                            PROPDMG,PROPDMGEXP,CROPDMG,CROPDMGEXP)

There we go. That will make it easier to work with this data set.

I also noticed that there is an abundance of weather events [985 unique names for that variable!]. That is a lot.

So let’s first limit ourselves to the top 10 events contributing to harming population health.

sum_fatalities <- Storm_HealthEconomic_Data %>%
        group_by(EVTYPE) %>%
        summarise(SUM_FATALITIES = sum(FATALITIES, na.rm = T), .groups = "drop")

sum_injuries <- Storm_HealthEconomic_Data %>%
        group_by(EVTYPE) %>%
        summarise(SUM_INJURIES = sum(INJURIES, na.rm = T), .groups = "drop")

top_10_fatal <- sum_fatalities %>% arrange(desc(SUM_FATALITIES)) %>% slice(1:10)
top_10_injuries <- sum_injuries %>% arrange(desc(SUM_INJURIES)) %>% slice (1:10)

Okey that is great. Below in the result section we will use this data (top_10_fatal and top_10_injuries) to make the final graphics that will help answer the question which type of events are most harmful for population health. But before we continue there, we also need to process the data in a meaningful way to see what event type has the greatest economic consequences.

unique(Storm_HealthEconomic_Data$PROPDMGEXP)
##  [1] "K" "M" ""  "B" "m" "+" "0" "5" "6" "?" "4" "2" "3" "h" "7" "H" "-" "1" "8"
unique(Storm_HealthEconomic_Data$CROPDMGEXP)
## [1] ""  "M" "K" "m" "B" "?" "0" "k" "2"

We observe that there are some weird variables that do not adhere to the expected values. We expected K or k for 1000, M or m for 1000.000, and B or b for 1000.000.000. However, we have some data errors.
Lets replace them with NA for now for the purpose of this analysis. And while we are at it, lets also replace the letters (K, M, B) with the actual numbers (1000, 1000.000, and 1000.000.000).

Storm_HealthEconomic_Data$PROPDMGEXP[!Storm_HealthEconomic_Data$PROPDMGEXP %in% c("K", "M", "B", "n", "b", "k")] <- NA ## replaces data entry errors in property damage with NA.
Storm_HealthEconomic_Data$CROPDMGEXP[!Storm_HealthEconomic_Data$CROPDMGEXP %in% c("K", "M", "B", "n", "b", "k")] <- NA ## replaces data entry errors in crop damage with NA. 

Storm_HealthEconomic_Data$PROPDMGEXP[Storm_HealthEconomic_Data$PROPDMGEXP %in% c("K", "k")] <- 1000
Storm_HealthEconomic_Data$PROPDMGEXP[Storm_HealthEconomic_Data$PROPDMGEXP %in% c("M","m")] <- 1000000
Storm_HealthEconomic_Data$PROPDMGEXP[Storm_HealthEconomic_Data$PROPDMGEXP %in% c("B","b")] <- 1000000000

Storm_HealthEconomic_Data$CROPDMGEXP[Storm_HealthEconomic_Data$CROPDMGEXP %in% c("K", "k")] <- 1000
Storm_HealthEconomic_Data$CROPDMGEXP[Storm_HealthEconomic_Data$CROPDMGEXP %in% c("M", "m")] <- 1000000
Storm_HealthEconomic_Data$CROPDMGEXP[Storm_HealthEconomic_Data$CROPDMGEXP %in% c("B", "b")] <- 1000000000

Perfect. Lets now calculate the combined total sum in USD for damages to property and crops.

Storm_HealthEconomic_Data$PROPERTYDAMAGE_USD <- Storm_HealthEconomic_Data$PROPDMG*as.numeric(Storm_HealthEconomic_Data$PROPDMGEXP) 

Storm_HealthEconomic_Data$CROP_USD <- Storm_HealthEconomic_Data$CROPDMG*as.numeric(Storm_HealthEconomic_Data$CROPDMGEXP) 

Storm_HealthEconomic_Data$combined_economic_damage_USD <- Storm_HealthEconomic_Data$PROPERTYDAMAGE_USD + Storm_HealthEconomic_Data$CROP_USD

Finally, we will look at the sum of the costs per event type and make a top 10 again of the event types with the highest costs.

sum_USD_costs <- Storm_HealthEconomic_Data %>%
        group_by(EVTYPE) %>%
        summarise(SUM_USD_COSTS = sum(combined_economic_damage_USD, na.rm = T), .groups = "drop")

top_10_economic_costs <- sum_USD_costs %>% arrange(desc(SUM_USD_COSTS)) %>% slice(1:10)

We will use the top_10_economic_costs to plot our findings and answer the question about economic costs below in the result section.

Results

1. Across the United States, which types of events are most harmful with respect to population health?

plot_fatal <- ggplot(data = top_10_fatal, aes(x = fct_reorder(EVTYPE, SUM_FATALITIES), y = SUM_FATALITIES)) +
        geom_col(fill = "red") + labs(x= "", y = "Fatalities", title = "Top 10 events causing fatalities") +
        coord_flip()

plot_injuries <- ggplot(data = top_10_injuries, aes(x = fct_reorder(EVTYPE, SUM_INJURIES), y = SUM_INJURIES)) +
        geom_col(fill = "orange") + labs(x= "", y = "Injuries", title = "Top 10 events causing injuries") +
        coord_flip()

plot_grid(plot_fatal, plot_injuries, nrow = 2)

It is clear from the graphs that TORNADO is the most dangerous event type for the population - as it contributes most to both injuries and fatalities. It is also worth noticing that both “Lighting” and “Excessive heat” are cross-cutting events that appear both in the top 5 for injuries and fatalities.

2. Across the United States, which types of events have the greatest economic consequences?

## plot economic outcome
plot_economic_cost <- ggplot(data = top_10_economic_costs, aes(x = fct_reorder(EVTYPE, SUM_USD_COSTS), y = SUM_USD_COSTS, fill = EVTYPE)) +
        geom_col() + labs(x= "", y = "Cost (USD)", title = "Top 10 event types and their overal costs") +
        coord_flip() + theme(legend.position = "none")
plot_economic_cost

It is clear from the graph that FLOOD is the most costly event type economically, followed by HURRICANE/TYPHOON. Lets look at the full numbers in USD for these two causes in a quick table:

top_10_economic_costs[1:2,]
## # A tibble: 2 × 2
##   EVTYPE            SUM_USD_COSTS
##   <chr>                     <dbl>
## 1 FLOOD              138007444500
## 2 HURRICANE/TYPHOON   29348167800

Wow, 138.007.444.500USD and 29.348.167.800USD! That is a lot of money.

Limitations

There are several limitations to the methodology of this reports and it’s findings. The main limitation to highlight in regards to the data processing is that there is an abundance of event types reported in the database (with 985 unique strings). It was not within the scope of this report to assess the 985 event strings and assess them for duplicates or merge them in ‘higher order events’ (for example by merging events such as “heat” and “excessive heat” in a shared category). This approach could of course have influenced the outcomes and it would be interesting if a more elaborate project looked into this.