Synopsis

In this report we explore the U.S. National Oceanic and Atmospheric Administration (NOAA) storm database. National Oceanic and Atmospheric Administration (NOAA). This database tracks characteristics of major storms and weather events in the United States, including when and where they occur, as well as estimates of any fatalities, injuries, and property damage. We will analyze the data to answer the following questions :

Our analysis concludes that:

Translated with DeepL.com (free version)

Data processing

Library loading

if(!require(dplyr)) install.packages("ggplot2", dependencies=TRUE)
## Loading required package: dplyr
## 
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
if(!require(ggplot2)) install.packages("ggplot2", dependencies=TRUE)
## Loading required package: ggplot2
if(!require(scales)) install.packages("ggplot2", dependencies=TRUE)
## Loading required package: scales
if(!require(gridExtra)) install.packages("ggplot2", dependencies=TRUE)
## Loading required package: gridExtra
## 
## Attaching package: 'gridExtra'
## The following object is masked from 'package:dplyr':
## 
##     combine
library(dplyr)
library(ggplot2)
library(scales)
library(gridExtra)

Downloading and reading the file

file_storm <- "./repdata_data_StormData.csv.bz2"
if(!file.exists(file_storm)) {
    url_storm <- "https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2"
    download.file(url = url_storm, destfile = file_storm)
}

df_storm <- read.csv(bzfile(file_storm))

After loading the data, we will check the first rows and the data structure.

head(df_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

For the purpose of our analysis, we will select only the columns we are interested in. 1. FATALITIES AND INJURIES columns inform us about the effect of storms and meteorological phenomena on the health of the population 2. 2. The columns PROPDMG, PROPDMGEXP and CROPDMG, CROPDMGEXP tell us about the economic damage caused by storms and weather events by estimating the approximate losses (in dollars) of goods and crops.

colsToSelect <- c("BGN_DATE","EVTYPE","FATALITIES","INJURIES","PROPDMG","PROPDMGEXP","CROPDMG","CROPDMGEXP")

df_storm_short <- df_storm[, colsToSelect]
head(df_storm_short)
##             BGN_DATE  EVTYPE FATALITIES INJURIES PROPDMG PROPDMGEXP CROPDMG
## 1  4/18/1950 0:00:00 TORNADO          0       15    25.0          K       0
## 2  4/18/1950 0:00:00 TORNADO          0        0     2.5          K       0
## 3  2/20/1951 0:00:00 TORNADO          0        2    25.0          K       0
## 4   6/8/1951 0:00:00 TORNADO          0        2     2.5          K       0
## 5 11/15/1951 0:00:00 TORNADO          0        2     2.5          K       0
## 6 11/15/1951 0:00:00 TORNADO          0        6     2.5          K       0
##   CROPDMGEXP
## 1           
## 2           
## 3           
## 4           
## 5           
## 6

Checking unique values in PROPDMGEXP and CROPDMGEXP to understand the different types of characters used to indicate the multiplication factor to be applied to PROPDMG and CROPDMG respectively.

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

From the above we can understand the following correspondences:

Add a column for transforming character symbols into their corresponding multiplication factor

df_storm_short <- df_storm_short %>% 
    mutate(PROPDMGEXP2 = case_when(
        (PROPDMGEXP == "h" | PROPDMGEXP == "H") ~ 100,
        (PROPDMGEXP == "k" | PROPDMGEXP == "K") ~ 1000,
        (PROPDMGEXP == "m" | PROPDMGEXP == "M") ~ 1000000,
        (PROPDMGEXP == "b" | PROPDMGEXP == "B") ~ 1000000000,
        PROPDMGEXP == "" ~ 1
    ),
    CROPDMGEXP2 = case_when(
        (CROPDMGEXP == "h" | CROPDMGEXP == "H") ~ 100,
        (CROPDMGEXP == "k" | CROPDMGEXP == "K") ~ 1000,
        (CROPDMGEXP == "m" | CROPDMGEXP == "M") ~ 1000000,
        (CROPDMGEXP == "b" | CROPDMGEXP == "B") ~ 1000000000,
        CROPDMGEXP == "" ~ 1
    ))

For the rest of the characters, we are NOT able to interpret the meaning. meaning. We will check how much data there is, apart from the characters we have identified, to understand the impact these data will have on our analysis

table(df_storm_short$PROPDMGEXP2, useNA = "ifany")
## 
##      1    100   1000  1e+06  1e+09   <NA> 
## 465934      7 424665  11337     40    314
table(df_storm_short$CROPDMGEXP2, useNA = "ifany")
## 
##      1   1000  1e+06  1e+09   <NA> 
## 618413 281853   1995      9     27

We can see here that the NA values, or the # of observations for which we were unable to interpret the characters, represent a very small percentage percent of the total number of observations. We will ignore the transformation of these observations.

calculation of the economic damage value with the derived multiplication factor derived factor

df_storm_short <- df_storm_short %>% 
    mutate(PROPDMGVAL = PROPDMG*PROPDMGEXP2,
           CROPDMGVAL = CROPDMG*CROPDMGEXP2)

Results

Question 1: In the United States, what types of events (indicated by the variable EVTYPE) are most damaging to the health of the population?

#fatalities2 <- tapply(df_storm_short$FATALITIES, df_storm_short$EVTYPE, sum)
#fatalities2 <- sort(fatalities2, decreasing = TRUE)
#fatalities2 <- fatalities2[1:10]

fatalities <- aggregate(FATALITIES ~ EVTYPE, df_storm_short, sum)
fatalities <- fatalities[order(-fatalities$FATALITIES), ]
fatalities <- fatalities[1:10,]
fatalities$EVTYPE <- factor(fatalities$EVTYPE, levels = fatalities$EVTYPE)

p1 <- ggplot(fatalities, aes(x = EVTYPE, y = FATALITIES)) + geom_bar(stat = "identity") + xlab("Event Type") + ylab("No of Fatalities") + ggtitle("Most Fatalities per Weather Event") + theme(axis.text.x = element_text(angle = 45, hjust = 1))

#injuries2 <- tapply(df_storm_short$INJURIES, df_storm_short$EVTYPE, sum)
#injuries2 <- sort(injuries2, decreasing = TRUE)
#injuries2 <- injuries2[1:10]

injuries <- aggregate(INJURIES ~ EVTYPE, df_storm_short, sum)
injuries <- injuries[order(-injuries$INJURIES),]
injuries <- injuries[1:10,]
injuries$EVTYPE <- factor(injuries$EVTYPE, levels = injuries$EVTYPE)

p2 <- ggplot(injuries, aes(x = EVTYPE, y = INJURIES)) + geom_bar(stat = "identity") + xlab("Event Type")+ ylab("No of Injuries") + ggtitle("Most Injuries per Weather Event") + theme(axis.text.x = element_text(angle = 45, hjust = 1))

grid.arrange(p1,p2, ncol = 2)

#### Answer 1: Tornado is the most damaging weather event to the health of the population.

Question 2: In the United States, what types of events have the greatest economic consequences?

damages <- aggregate(PROPDMGVAL + CROPDMGVAL ~ EVTYPE, df_storm_short, sum)
names(damages) <- c("EVTYPE", "TOTDMG")
damages <- damages[order(-damages$TOTDMG), ]
damages <- damages[1:10, ]
damages$EVTYPE <- factor(damages$EVTYPE, levels = damages$EVTYPE)

p3 <- ggplot(damages, aes(x = EVTYPE, y = TOTDMG)) + geom_bar(stat = "identity") + xlab("Event Type") +  ylab("Damages $") + ggtitle("Most Damgages (in USD) per Weather Event") + theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7)) + scale_y_continuous(labels = label_number(suffix = " Bn", scale = 1e-09))

damages_nObs <- df_storm_short %>% 
    count(EVTYPE)
damages_nObs <- damages_nObs[damages_nObs$EVTYPE %in% damages[,1],]
damages_nObs$EVTYPE <- factor(damages_nObs$EVTYPE, levels = damages$EVTYPE)

p4<- ggplot(damages_nObs, aes(x = EVTYPE, y = n)) + geom_bar(stat = "identity") + geom_text(aes(label = n), vjust = -0.3, size = 3) + xlab("Event Type") + ylab("No of Events") + ggtitle("No of Events per Event Type") + theme(axis.text.x = element_text(angle = 45, hjust = 1, size = 7)) + scale_y_continuous(labels = label_number(suffix = "K", scale = 1e-03))

grid.arrange(p3,p4)

#### Answer 2: Floods have had the greatest economic consequences. However, if you look at the corresponding number of events, hurricanes and typhoons are the deadliest weather events with the greatest economic damage per event.