Reproducible Research Assignment # 2
Rafael Posada Velázquez
Storms and other severe weather events can cause both public health and economic problems for communities and municipalities. Many severe events can result in fatalities, injuries, and property damage, and preventing such outcomes to the extent possible is a key concern.
In the following pages I will explore the U.S. National Oceanic and Atmospheric Administration’s (NOAA) storm database. 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.
I will then present the impact of severe weather events on health and economics categorized by kind of event. In order to have the whole analysis clear, I will specify each step of the analysis from loading the data to the process of making tables and plots.
You will see that tornadoes are the most harmful for both health reasons with 5633 deaths and 91346 injuries. On the economic front, floods have caused most losses with 144.6 billion dollars worth of losses in property and another 5.6 billions in crop losses. Nevertheless, drought has caused more crop losses than floods with a total of 13.9 billions worth of losses.
# To avoid version warnings
options(scipen=999)
if (!requireNamespace("data.table", quietly = TRUE)) {install.packages("data.table")}
if (!requireNamespace("R.utils", quietly = TRUE)) {install.packages("R.utils")}
if (!requireNamespace("flextable", quietly = TRUE)) {install.packages("flextable")}
# Load libraries
library(data.table)
library(flextable)
# Set working directory and read data
setwd("D:/OneDrive - Rafael Posada Velázquez/OneDrive/00. Cursos tomados/01. Data Science/5. Reproducible research/Assignment2")
if (!file.exists("repdata_data_StormData.csv.bz2")){download.file("https://d396qusza40orc.cloudfront.net/repdata%2Fdata%2FStormData.csv.bz2", "repdata_data_StormData.csv.bz2")
}
DF<-fread("repdata_data_StormData.csv.bz2")
We want to be sure the data has loaded correctly and get to know what kind of data we have. So we check the structure of the dataframe first.
str(DF)
## Classes 'data.table' and 'data.frame': 902297 obs. of 37 variables:
## $ STATE__ : num 1 1 1 1 1 1 1 1 1 1 ...
## $ BGN_DATE : chr "4/18/1950 0:00:00" "4/18/1950 0:00:00" "2/20/1951 0:00:00" "6/8/1951 0:00:00" ...
## $ BGN_TIME : chr "0130" "0145" "1600" "0900" ...
## $ TIME_ZONE : chr "CST" "CST" "CST" "CST" ...
## $ COUNTY : num 97 3 57 89 43 77 9 123 125 57 ...
## $ COUNTYNAME: chr "MOBILE" "BALDWIN" "FAYETTE" "MADISON" ...
## $ STATE : chr "AL" "AL" "AL" "AL" ...
## $ EVTYPE : chr "TORNADO" "TORNADO" "TORNADO" "TORNADO" ...
## $ BGN_RANGE : num 0 0 0 0 0 0 0 0 0 0 ...
## $ BGN_AZI : chr "" "" "" "" ...
## $ BGN_LOCATI: chr "" "" "" "" ...
## $ END_DATE : chr "" "" "" "" ...
## $ END_TIME : chr "" "" "" "" ...
## $ COUNTY_END: num 0 0 0 0 0 0 0 0 0 0 ...
## $ COUNTYENDN: logi NA NA NA NA NA NA ...
## $ END_RANGE : num 0 0 0 0 0 0 0 0 0 0 ...
## $ END_AZI : chr "" "" "" "" ...
## $ END_LOCATI: chr "" "" "" "" ...
## $ LENGTH : num 14 2 0.1 0 0 1.5 1.5 0 3.3 2.3 ...
## $ WIDTH : num 100 150 123 100 150 177 33 33 100 100 ...
## $ F : int 3 2 2 2 2 2 2 1 3 3 ...
## $ MAG : num 0 0 0 0 0 0 0 0 0 0 ...
## $ FATALITIES: num 0 0 0 0 0 0 0 0 1 0 ...
## $ INJURIES : num 15 0 2 2 2 6 1 0 14 0 ...
## $ PROPDMG : num 25 2.5 25 2.5 2.5 2.5 2.5 2.5 25 25 ...
## $ PROPDMGEXP: chr "K" "K" "K" "K" ...
## $ CROPDMG : num 0 0 0 0 0 0 0 0 0 0 ...
## $ CROPDMGEXP: chr "" "" "" "" ...
## $ WFO : chr "" "" "" "" ...
## $ STATEOFFIC: chr "" "" "" "" ...
## $ ZONENAMES : chr "" "" "" "" ...
## $ LATITUDE : num 3040 3042 3340 3458 3412 ...
## $ LONGITUDE : num 8812 8755 8742 8626 8642 ...
## $ LATITUDE_E: num 3051 0 0 0 0 ...
## $ LONGITUDE_: num 8806 0 0 0 0 ...
## $ REMARKS : chr "" "" "" "" ...
## $ REFNUM : num 1 2 3 4 5 6 7 8 9 10 ...
## - attr(*, ".internal.selfref")=<externalptr>
Now we present a summary of each variable to get to know what kind of information we have.
summary(DF)
## STATE__ BGN_DATE BGN_TIME TIME_ZONE
## Min. : 1.0 Length:902297 Length:902297 Length:902297
## 1st Qu.:19.0 Class :character Class :character Class :character
## Median :30.0 Mode :character Mode :character Mode :character
## Mean :31.2
## 3rd Qu.:45.0
## Max. :95.0
##
## COUNTY COUNTYNAME STATE EVTYPE
## Min. : 0.0 Length:902297 Length:902297 Length:902297
## 1st Qu.: 31.0 Class :character Class :character Class :character
## Median : 75.0 Mode :character Mode :character Mode :character
## Mean :100.6
## 3rd Qu.:131.0
## Max. :873.0
##
## BGN_RANGE BGN_AZI BGN_LOCATI END_DATE
## Min. : 0.000 Length:902297 Length:902297 Length:902297
## 1st Qu.: 0.000 Class :character Class :character Class :character
## Median : 0.000 Mode :character Mode :character Mode :character
## Mean : 1.484
## 3rd Qu.: 1.000
## Max. :3749.000
##
## END_TIME COUNTY_END COUNTYENDN END_RANGE
## Length:902297 Min. :0 Mode:logical Min. : 0.0000
## Class :character 1st Qu.:0 NA's:902297 1st Qu.: 0.0000
## Mode :character Median :0 Median : 0.0000
## Mean :0 Mean : 0.9862
## 3rd Qu.:0 3rd Qu.: 0.0000
## Max. :0 Max. :925.0000
##
## END_AZI END_LOCATI LENGTH WIDTH
## Length:902297 Length:902297 Min. : 0.0000 Min. : 0.000
## Class :character Class :character 1st Qu.: 0.0000 1st Qu.: 0.000
## Mode :character Mode :character Median : 0.0000 Median : 0.000
## Mean : 0.2301 Mean : 7.503
## 3rd Qu.: 0.0000 3rd Qu.: 0.000
## Max. :2315.0000 Max. :4400.000
##
## F MAG FATALITIES INJURIES
## Min. :0.0 Min. : 0.0 Min. : 0.0000 Min. : 0.0000
## 1st Qu.:0.0 1st Qu.: 0.0 1st Qu.: 0.0000 1st Qu.: 0.0000
## Median :1.0 Median : 50.0 Median : 0.0000 Median : 0.0000
## Mean :0.9 Mean : 46.9 Mean : 0.0168 Mean : 0.1557
## 3rd Qu.:1.0 3rd Qu.: 75.0 3rd Qu.: 0.0000 3rd Qu.: 0.0000
## Max. :5.0 Max. :22000.0 Max. :583.0000 Max. :1700.0000
## NA's :843563
## PROPDMG PROPDMGEXP CROPDMG CROPDMGEXP
## Min. : 0.00 Length:902297 Min. : 0.000 Length:902297
## 1st Qu.: 0.00 Class :character 1st Qu.: 0.000 Class :character
## Median : 0.00 Mode :character Median : 0.000 Mode :character
## Mean : 12.06 Mean : 1.527
## 3rd Qu.: 0.50 3rd Qu.: 0.000
## Max. :5000.00 Max. :990.000
##
## WFO STATEOFFIC ZONENAMES LATITUDE
## Length:902297 Length:902297 Length:902297 Min. : 0
## Class :character Class :character Class :character 1st Qu.:2802
## Mode :character Mode :character Mode :character Median :3540
## Mean :2875
## 3rd Qu.:4019
## Max. :9706
## NA's :47
## LONGITUDE LATITUDE_E LONGITUDE_ REMARKS
## Min. :-14451 Min. : 0 Min. :-14455 Length:902297
## 1st Qu.: 7247 1st Qu.: 0 1st Qu.: 0 Class :character
## Median : 8707 Median : 0 Median : 0 Mode :character
## Mean : 6940 Mean :1452 Mean : 3509
## 3rd Qu.: 9605 3rd Qu.:3549 3rd Qu.: 8735
## Max. : 17124 Max. :9706 Max. :106220
## NA's :40
## REFNUM
## Min. : 1
## 1st Qu.:225575
## Median :451149
## Mean :451149
## 3rd Qu.:676723
## Max. :902297
##
Given that the events were recorded with lower case and upper case, abbreviations and with additional spaces we standardized it with the following code.
# Rename variables for easy recognition in code
Event <-DF$EVTYPE
Fatalities <-DF$FATALITIES
Injuries <-DF$INJURIES
# The events were recorded with lower case and upper case, abbreviations and some strings have additional spaces or different separators (other than spaces) that can be fixed with the following code
Event<-toupper(Event)
Event<-trimws(Event)
Event <- gsub("[[:blank:][:punct:]+]", " ", Event)
Event<-gsub("TSTM", "THUNDERSTORM", Event)
Event<-gsub("WND", "WIND", Event)
Event<-gsub("RIP CURRENTS", "RIP CURRENT", Event)
Event<-gsub("THUNDERSTORM WINDS", "THUNDERSTORM WIND", Event)
Event<-gsub(" ", " ", Event)
Event<-gsub("TORNADOES THUNDERSTORM WIND HAIL", "TORNADO", Event)
Event<-gsub("HEAVY RAIN SEVERE WEATHER", "HEAVY RAIN", Event)
Event<-gsub("EXTREME COLD WIND CHILL", "EXTREME COLD", Event)
Event<-gsub("COLD WIND CHILL", "EXTREME COLD", Event)
Event<-gsub("TORNADOES THUNDERSTORM WIND HAIL", "TORNADO", Event)
Event<-gsub(" ", " ", Event)
Property and crop damages are expressed in different units (dollars, hundreds, thousands, millions or billions of dollars), so we first convert abbreviations into exponents from the variable PROPDMGEXP, and then we calculate the damage in dollars multiplying PROPDMG times 10 to the exponent.
PropExp <-DF$PROPDMGEXP
PropExp[PropExp=="B"]<-9
PropExp[PropExp=="m"]<-6
PropExp[PropExp=="M"]<-6
PropExp[PropExp=="K"]<-3
PropExp[PropExp=="h"]<-2
PropExp[PropExp=="H"]<-2
PropExp[PropExp=="-"]<-0
PropExp[PropExp=="?"]<-0
PropExp[PropExp=="+"]<-0
PropExp[PropExp==""] <-0
PropExp <-as.numeric(PropExp)
CropExp <-DF$CROPDMGEXP
CropExp[CropExp=="B"]<-9
CropExp[CropExp=="m"]<-6
CropExp[CropExp=="M"]<-6
CropExp[CropExp=="k"]<-3
CropExp[CropExp=="K"]<-3
CropExp[CropExp=="?"]<-0
CropExp[CropExp==""] <-0
CropExp <-as.numeric(CropExp)
# Calculate loss in USD with easily recognizable names
Property <-DF$PROPDMG*(10^PropExp)
Crop <-DF$CROPDMG*(10^CropExp)
FatalitiesTable <- aggregate(Fatalities, by = list(Event), FUN= sum)
names(FatalitiesTable)<-c("Event","Fatalities")
FatalitiesTable <- FatalitiesTable[order(FatalitiesTable$Fatalities, decreasing = TRUE), ]
FatalitiesTable <- FatalitiesTable[1:20,]
FatalitiesTable$Event<-factor(FatalitiesTable$Event, levels = FatalitiesTable$Event)
width(flextable(FatalitiesTable), width = 3, j = 1)
Event | Fatalities |
|---|---|
TORNADO | 5,658 |
EXCESSIVE HEAT | 1,903 |
FLASH FLOOD | 978 |
HEAT | 937 |
LIGHTNING | 816 |
THUNDERSTORM WIND | 701 |
RIP CURRENT | 572 |
FLOOD | 470 |
EXTREME COLD | 382 |
HIGH WIND | 248 |
AVALANCHE | 224 |
WINTER STORM | 206 |
HEAT WAVE | 172 |
HEAVY SNOW | 127 |
HIGH SURF | 104 |
STRONG WIND | 103 |
BLIZZARD | 101 |
HEAVY RAIN | 98 |
EXTREME HEAT | 96 |
ICE STORM | 89 |
InjuriesTable <- aggregate(Injuries, by = list(Event), FUN= sum)
names(InjuriesTable)<-c("Event","Injuries")
InjuriesTable <- InjuriesTable[order(InjuriesTable$Injuries, decreasing = TRUE), ]
InjuriesTable <- InjuriesTable[1:20,]
InjuriesTable$Event<-factor(InjuriesTable$Event, levels = InjuriesTable$Event)
width(flextable(InjuriesTable), width = 3, j = 1)
Event | Injuries |
|---|---|
TORNADO | 91,346 |
THUNDERSTORM WIND | 9,353 |
FLOOD | 6,789 |
EXCESSIVE HEAT | 6,525 |
LIGHTNING | 5,230 |
HEAT | 2,100 |
ICE STORM | 1,975 |
FLASH FLOOD | 1,777 |
HAIL | 1,361 |
WINTER STORM | 1,321 |
HURRICANE TYPHOON | 1,275 |
HIGH WIND | 1,137 |
HEAVY SNOW | 1,021 |
WILDFIRE | 911 |
BLIZZARD | 805 |
FOG | 734 |
WILD FOREST FIRE | 545 |
RIP CURRENT | 529 |
DUST STORM | 440 |
WINTER WEATHER | 398 |
par(mfcol=c(1,2), mar=c(12, 5, 6, 2),cex=.8)
barplot(Fatalities ~ Event, data = FatalitiesTable, las=2,col="royalblue",xlab="", main ="Fatalities caused by kind of event")
barplot(Injuries ~ Event, data = InjuriesTable, las=2,col="royalblue",xlab="", main ="Injuries caused by kind of event")
mtext("Figure 1. Health issues by kind of severe weather event", side = 3, line = -2, cex = 1.5,outer = TRUE)
To address the question of which types of events are most harmful to population health, we can see that tornadoes are the most harmful by far, both for number of deaths and injuries caused by the event. Excessive heat is the second event that causes the most amount of deaths and thunderstorm winds the most amount of injuries.
CropTable <- aggregate(Crop, by = list(Event), FUN= sum)
names(CropTable)<-c("Event","Crop")
CropTable <- CropTable[order(CropTable$Crop, decreasing = TRUE), ]
CropTable <- CropTable[1:20,]
CropTable$Event<-factor(CropTable$Event, levels = CropTable$Event)
width(flextable(CropTable), width = 3, j = 1)
Event | Crop |
|---|---|
DROUGHT | 13,972,566,000 |
FLOOD | 5,661,968,450 |
RIVER FLOOD | 5,029,459,000 |
ICE STORM | 5,022,113,500 |
HAIL | 3,025,954,473 |
HURRICANE | 2,741,910,000 |
HURRICANE TYPHOON | 2,607,872,800 |
FLASH FLOOD | 1,421,317,100 |
EXTREME COLD | 1,313,623,000 |
THUNDERSTORM WIND | 1,159,505,188 |
FROST FREEZE | 1,094,186,000 |
HEAVY RAIN | 733,399,800 |
TROPICAL STORM | 678,346,000 |
HIGH WIND | 638,571,300 |
EXCESSIVE HEAT | 492,402,000 |
FREEZE | 456,725,000 |
TORNADO | 417,453,270 |
HEAT | 401,461,500 |
DAMAGING FREEZE | 296,230,000 |
WILDFIRE | 295,472,800 |
PropertyTable <- aggregate(Property, by = list(Event), FUN= sum)
names(PropertyTable)<-c("Event","Property")
PropertyTable <- PropertyTable[order(PropertyTable$Property, decreasing = TRUE), ]
PropertyTable <- PropertyTable[1:20,]
PropertyTable$Event<-factor(PropertyTable$Event, levels = PropertyTable$Event)
width(flextable(PropertyTable), width = 3, j = 1)
Event | Property |
|---|---|
FLOOD | 144,657,709,807 |
HURRICANE TYPHOON | 69,305,840,000 |
TORNADO | 58,547,380,677 |
STORM SURGE | 43,323,536,000 |
FLASH FLOOD | 16,822,723,979 |
HAIL | 15,735,267,513 |
HURRICANE | 11,868,319,010 |
THUNDERSTORM WIND | 9,920,830,826 |
TROPICAL STORM | 7,703,890,550 |
WINTER STORM | 6,688,497,251 |
HIGH WIND | 5,270,046,295 |
RIVER FLOOD | 5,118,945,500 |
WILDFIRE | 4,765,114,000 |
STORM SURGE TIDE | 4,641,188,000 |
ICE STORM | 3,944,927,860 |
HEAVY RAIN | 3,194,248,090 |
HURRICANE OPAL | 3,172,846,000 |
WILD FOREST FIRE | 3,001,829,500 |
SEVERE THUNDERSTORM | 1,205,360,000 |
DROUGHT | 1,046,106,000 |
par(mfcol=c(1,2), mar=c(12, 5, 6, 2),cex=.8)
barplot(Crop/1000000000 ~ Event, data = CropTable, las=2,col="royalblue",xlab="", main ="Damaged crops by kind of event",ylab="Crop losses (in billions of USD)")
barplot(Property/1000000000 ~ Event, data = PropertyTable, las=2,col="royalblue",xlab="", main ="Damaged property caused by kind of event",ylab="Property losses (in billions of USD)")
mtext("Figure 2. Economic consequences by kind of severe weather event", side = 3, line = -2, cex = 1.5,outer = TRUE)
To address the question of which types of events are have the greatest economic consequences, floods are the most expensive with over 144 billion dollars on property loss and 5.6 billions in crop losses. Nevertheless, drought has the worst impact on crops with 13.9 Billiosn on losses.