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.
From offical record, various type of natural events have cause tens of thousand fatality and 400 billion USD worth of economic lost, This Study is to find what type of event have biggest impact.
U.S. National Oceanic and Atmospheric Administration’s (NOAA) storm database collected natural events since 1950, it recorded fatalities, injuries, property damage and crop damage data. although only recent years appears have complete records, but it is good source to explore. We will look at number of fatality, injure, and value of damage each event caused.
Data is in comma separeated CSV file, file can be download from this link, the file is compressed in bzip2 format, uncompress before read into R.
dat<-read.csv("repdata%2Fdata%2FStormData.csv.bz2", stringsAsFactors = F)
# summarize by year
dat$date<-strptime(dat$BGN_DATE, "%m/%d/%Y %H:%M:%S")
dat$year<-dat$date$year+1900
dat$date<-as.character(dat$date) # this column will not be use again actually
total_Obj<-dim(dat)[1]
quantile(dat$year)
## 0% 25% 50% 75% 100%
## 1950 1995 2002 2007 2011
# remove lower 25%
dat<-dat[dat$year>=1995,]
total_obj<-dim(dat)[1]
National Weather Service indicates the data is collected since 1950, until 2011, there are 902297 events in data set, however, most data are collected after year 2002, we will skip lower 25% of data in favor of complete yearly observation. The subset of data is 681500 events, from 1995 until 2011.
dataset has 2 column for each damage type, one column store the number, another column store exponent, like “m” for million, “H” for handred. we first need to convert the exponent to number.
How To Handle Exponent Value of PROPDMGEXP and CROPDMGEXP guide has comperhansive study of how to handle each exponent, below is descipition
H,h,K,k,M,m,B,b,+,-,?,0,1,2,3,4,5,6,7,8, and blank-character
H,h = hundreds = 100
K,k = kilos = thousands = 1,000
M,m = millions = 1,000,000
B,b = billions = 1,000,000,000
(+) = 1
(-) = 0
(?) = 0
black/empty character = 0
numeric 0..8 = 10
conclusion for all numeric, exp 0, 1, 2, 3, 4, 5, 6, 7, 8, they are multiplier of 10.
we will create a function take exponent charactor and create multiplication factor, use this factor multiply with damage value.
# function take two vector and multiply
expval<-function(v,e) {
if ( length(v) != length(e)) {
message("2 vectors not at same length")
return()
}
# the order doesnt matter, all gsub will run anyway,
# only order matters is number be first, so that 10 will not be replace again
e <- sub("^[0|1|2|3|4|5|6|7|8]$", "10", e)
e <- sub("^$", "0", e)
e <- sub("^[-|?]$", "0", e)
e <- sub("^\\+$", "1", e)
e <- sub("^[h|H]$", "100", e)
e <- sub("^[k|K]$", "1000", e)
e <- sub("^[m|M]$", "1000000", e)
e <- sub("^[b|B]$", "1000000000", e)
e <- as.numeric(e)
return (v * e)
}
we will create two new column for dataset, propval for property damange value, cropval fro crop damage value
# calculate property and crop danmage
dat$propval <- expval(dat$PROPDMG, dat$PROPDMGEXP)
dat$cropval <- expval(dat$CROPDMG, dat$CROPDMGEXP)
the detail description of dataset can be found in National Weather Service Storm Data Documentation. extract “Storm Data Event” and save to text file.
evtcat <- read.csv("evtcat.txt", header = F)
eventcat<-sort(toupper((evtcat[,1])))
rm(evtcat)
According to 2.1.1 Storm Data Event Table, there are 48 types of event, but there are 799 event names reported. In order to produce meaningful result, we first need to clean up the event name of each event. The plan as following
first, supporting functions
# function that match orignal event name with pattern, if found assign offical name to event_type column
# ep is vector of patterns that will apply to orignal names
# ec is vector of list of offical names, pair will patterns
match_event <- function(ep,em) {
for ( i in 1:length(ep)) {
#print(paste("replacing ",ep[i],"with",em[i], sep = " "))
events[grep(ep[i],events$evtype),] %<>% mutate(event_type = em[i])
events<<-events
}
}
# subset event from dataset
evts<-toupper(trimws(as.vector(dat$EVTYPE)))
events<-cbind(evts, evts,rep(NA,length(evts)))
colnames(events)<-c("evtype","event_type","event_cat")
events<-tbl_df(events)
rm(evts)
event_patterns <- c("^TSTM$")
event_matches <- c("THUNDERSTORM")
match_event(event_patterns, event_matches)
# assign offical name if cleaned up event_name is offical name
for ( e in eventcat) {
events[events$event_type==e, "event_cat"]<-e
}
repeat step 4 to 6, until top unassigned event is insignificate.
events %>% filter(is.na(event_cat)) %>% group_by(event_type) %>% summarise(cnt=n()) %>% arrange(desc(cnt))
## # A tibble: 662 x 2
## event_type cnt
## <chr> <int>
## 1 TSTM WIND 128929
## 2 THUNDERSTORM WINDS 10041
## 3 MARINE TSTM WIND 6175
## 4 URBAN/SML STREAM FLD 3392
## 5 WILD/FOREST FIRE 1446
## 6 WINTER WEATHER/MIX 1104
## 7 TSTM WIND/HAIL 1028
## 8 HIGH WINDS 776
## 9 EXTREME COLD 634
## 10 LANDSLIDE 599
## # ... with 652 more rows
list of patterns after over 10 rounds of matching, the number of of event is low enough, how ever we need to consider smaller number of event but having bigger impact.
options(width=80)
# pattern of evtype
event_patterns <- c(
"^(TSTM|TSTM WIND|THUNDERSTORM WINDS)$",
"^MARINE TSTM WIND$",
"^(URBAN/SML STREAM FLD|URBAN FLOOD|RIVER FLOOD(ING)?|FLOOD/FLASH FLOOD)$",
"^(HIGH WINDS|WIND)", # high winds or start with wind
"^WILD/FOREST FIRE$",
"^WINTER WEATHER/MIX$",
"^(TSTM WIND/HAIL|HAILSTORM)$",
"^EXTREME COLD$",
"^SNOW$",
"^FOG$",
"^RIP CURRENTS$",
"^STORM SURGE$",
"^(FREEZING RAIN|GLAZE)$",
"^HEAVY SURF/HIGH SURF$",
"^EXTREME WINDCHILL$",
"^STRONG WINDS$",
"^(HURRICANE|TYPHOON)", # named hurricane
"^ASTRONOMICAL (LOW|HIGH) TIDE$",
"^COLD$",
"^(FREEZE|DAMAGING FREEZE)$",
"^HEAVY RAIN",
"^COASTAL FLOODING$",
"^FLASH FLOODING$",
"^SEVERE THUNDERSTORM$",
"^(HEAT WAVE|UNSEASONABLY WARM AND DRY|UNSEASONABLY WARM)$",
"^EXTREME HEAT$"
)
# replaced with, elementes must match with associated pattern as pair
event_matches <- c(
"THUNDERSTORM WIND",
"MARINE THUNDERSTORM WIND",
"FLOOD",
"HIGH WIND",
"WILDFIRE",
"WINTER WEATHER",
"HAIL",
"EXTREME COLD/WIND CHILL",
"HEAVY SNOW",
"DENSE FOG",
"RIP CURRENT",
"STORM SURGE/TIDE",
"SLEET",
"HIGH SURF",
"EXTREME COLD/WIND CHILL",
"STRONG WIND",
"HURRICANE (TYPHOON)",
"ASTRONOMICAL LOW TIDE",
"COLD/WIND CHILL",
"FROST/FREEZE",
"HEAVY RAIN",
"COASTAL FLOOD",
"FLASH FLOOD",
"THUNDERSTORM WIND",
"HEAT",
"EXCESSIVE HEAT"
)
# step 4
match_event(event_patterns, event_matches)
# step 5
for ( e in eventcat) {
events[events$event_type==e, "event_cat"]<-e
}
# add result back to data set
dat$event_cat <- events$event_cat
After finish will “count”, and adding event_cat back to dataset, run more verification, sort by fataility, injure, and damage value. create more pattern/matches, and clean up again step 4 to 6. this will take another 5 to 10 tries.
# step 6
dat %>%
filter(is.na(event_cat)) %>%
group_by(EVTYPE) %>%
summarize(
cnt = n(),
total_fat = sum(FATALITIES),
total_inj = sum(INJURIES),
total_propval = round(sum(propval)/1000000,2),
total_cropval = round(sum(cropval)/1000000,2)
) %>%
arrange(desc(total_fat))
## # A tibble: 646 x 6
## EVTYPE cnt total_fat total_inj total_propval
## <chr> <int> <dbl> <dbl> <dbl>
## 1 LANDSLIDE 599 38 52 324.60
## 2 COLD AND SNOW 1 14 0 0.00
## 3 ROUGH SEAS 3 8 5 0.00
## 4 MARINE MISHAP 2 7 5 0.00
## 5 HEAVY SURF 82 6 40 1.34
## 6 COLD WEATHER 4 5 0 0.00
## 7 ICY ROADS 28 5 31 0.34
## 8 RIP CURRENTS/HEAVY SURF 2 5 0 0.00
## 9 HEAT WAVE DROUGHT 1 4 15 0.20
## 10 Hypothermia/Exposure 3 4 0 0.00
## # ... with 636 more rows, and 1 more variables: total_cropval <dbl>
# unassigned rows
dat %>% group_by(is.na(event_cat)) %>% summarize(
cnt=n(),
total_fat = sum(FATALITIES),
total_inj = sum(INJURIES),
total_propval = round(sum(propval)/1000000,2),
total_cropval = round(sum(cropval)/1000000,2)
)
## # A tibble: 2 x 6
## `is.na(event_cat)` cnt total_fat total_inj total_propval
## <lgl> <int> <dbl> <dbl> <dbl>
## 1 FALSE 677551 10029 61821 376052.73
## 2 TRUE 3949 194 634 506.92
## # ... with 1 more variables: total_cropval <dbl>
This is final result, the summary shows that after clean up, the number of un-catagorized, total injure, total property damange value, total crop damage val are all between 1 to 2%.
Note the landside cause total 38 death, which is high but there’s no catelog to match to, landside could cause by rain or snow, we leave it as is.
At this point, we are ready to process data.
take orignal dataset, group by offical event names, in each group, summarize the number of fatality/injuries, for damage type event, summarize the value, then sort the result, lastly pick top 20 result. the reason I pick 20 is to keep “other” low enough.
create a total count/value for later percentage calculation.
find the events that are outside of top 20, assign the event name as “OTHER”, their value is either number of occurence, or sum of value for damage type.
add the row of others to result data frame
create data frame for treemap display, the lable is combination of event name and percentage.
# top fatality
top_fat<-dat %>%
group_by(event_cat) %>%
summarize(total= sum(FATALITIES)) %>%
arrange(desc(total)) %>% top_n(20)
total_cnt<-sum(dat$FATALITIES)
other_cnt<-dat %>%
filter(!event_cat %in% top_fat$event_cat) %>%
group_by(event_cat) %>%
summarise(total=sum(FATALITIES)) %>%
select(total) %>%
sum()
top_fat[nrow(top_fat)+1,] <- list("OTHERS",other_cnt)
top_fat$pct<-round(top_fat$total/total_cnt*100,2)
top_fat_tm<-data.frame(event_cat=paste(top_fat$event_cat,"(",top_fat$pct,"%)", sep=""), total=top_fat$total)
# top injure
top_inj<-dat %>%
group_by(event_cat) %>%
summarize(total= sum(INJURIES)) %>%
arrange(desc(total)) %>% top_n(20)
total_cnt<-sum(dat$INJURIES)
other_cnt<-dat %>%
filter(!event_cat %in% top_inj$event_cat) %>%
group_by(event_cat) %>%
summarise(total=sum(INJURIES)) %>%
select(total) %>%
sum()
top_inj[nrow(top_inj)+1,] <- list("OTHERS",other_cnt)
top_inj$pct<-round(top_inj$total/total_cnt*100,2)
top_inj_tm<-data.frame(event_cat=paste(top_inj$event_cat,"(",top_inj$pct,"%)", sep=""), total=top_inj$total)
# top property damange
top_prop<-dat %>%
group_by(event_cat) %>%
summarize(total= round(sum(propval)/1000000)) %>%
arrange(desc(total)) %>% top_n(20)
total_cnt<-round(sum(dat$propval)/1000000)
other_cnt<-dat %>%
filter(!event_cat %in% top_prop$event_cat) %>%
group_by(event_cat) %>%
summarise(total=round(sum(propval)/1000000)) %>%
select(total) %>%
sum()
top_prop[nrow(top_prop)+1,] <- list("OTHERS",other_cnt)
top_prop$pct<-round(top_prop$total/total_cnt*100,2)
top_prop_tm<-data.frame(event_cat=paste(top_prop$event_cat,"(",top_prop$pct,"%)", sep=""), total=top_prop$total)
# top crop damage
top_crop<-dat %>%
group_by(event_cat) %>%
summarize(total= round(sum(cropval)/1000000)) %>%
arrange(desc(total)) %>% top_n(20)
total_cnt<-round(sum(dat$cropval)/1000000)
other_cnt<-dat %>%
filter(!event_cat %in% top_crop$event_cat) %>%
group_by(event_cat) %>%
summarise(total=round(sum(cropval)/1000000)) %>%
select(total) %>%
sum()
top_crop[nrow(top_crop)+1,] <- list("OTHERS",other_cnt)
top_crop$pct<-round(top_crop$total/total_cnt*100,2)
top_crop_tm<-data.frame(event_cat=paste(top_crop$event_cat,"(",top_crop$pct,"%)", sep=""), total=top_crop$total)
Each state have different top event, we will create top most event in terms of casuing fatality, injures, perproty damage, and crop damage.
get list of state code and state name, for user friendly display
group dataset into state_name, event_cat, in that order, summarize either by count of value, arrange result n=in descending order, filter by state_name, reduce value to million if necessary.
merge four data frame to one.
assign column names with clear meaning
# read state name
state<-read.csv("state.txt",sep = "\t", stringsAsFactors = F)
# create new column in data set for state name
dat$state_name<-state$name[match(dat$STATE, state$code)]
# top property
state_prop <- dat %>%
group_by(state_name,event_cat) %>%
summarise(total_prop=sum(propval)) %>%
arrange(desc(total_prop)) %>%
filter(row_number(state_name) < 2) %>%
mutate(total_prop=round(total_prop/1000000))
# top crop
state_crop <- dat %>%
group_by(state_name,event_cat) %>%
summarise(total_crop=sum(cropval)) %>%
arrange(desc(total_crop)) %>%
filter(row_number(state_name) < 2) %>%
mutate(total_crop=round(total_crop/1000000))
# top fatality
state_fat <- dat %>%
group_by(state_name,event_cat) %>%
summarise(total_fat=sum(FATALITIES)) %>%
arrange(desc(total_fat)) %>%
filter(row_number(state_name) <2)
# top injure
state_inj<-dat %>%
group_by(state_name,event_cat) %>%
summarise(total_inj=sum(INJURIES)) %>%
arrange(desc(total_inj)) %>%
filter(row_number(state_name) <2)
# merge 4 data frame into one as top event
state_tops<-merge(state_fat, state_inj, by="state_name")
state_tops<-merge(state_tops, state_prop, by="state_name")
state_tops<-merge(state_tops, state_crop, by="state_name")
# assign user friendly header
colnames(state_tops)<-c("State",
"Event Caused Most Fatality", "Fatality Count",
"Event Caused most Injure", "Injure Count",
"Event caused most Property Damage","Damage Value (Million)",
"Event Caused Most Crop Damage","Damage Value (Million)"
)
As mentioned in the begining, natural events have had great impact to public health and economic. there are total 10223 fatalities, 62455 injuries. Also, it caused economic lost in 376.6 billion USD of perproty, 37.7 billion crop damage, total 414.3 billion UDS.
Natural events that cause most fatality and injures are considered most harmful, in United States excesive heat caused most fatality, “EXCESSIVE HEAT” event is responsible for near 20% of death, Tornado come to second place by small margin, but considering “HEAT”’s 11%, extrem hot weather is single most deadly natural event. In terms of injures, “TORNADO” is far ahead of other event, it count for 34.85% of all injuries, near twice of “EXCESSIVE HEAT” and “HEAT” combined.
grid.newpage()
pushViewport(viewport(layout=grid.layout(2,1)))
vp_fat<-viewport(layout.pos.col=1, layout.pos.row=1)
treemap(top_fat_tm, index=c("event_cat","total"), vSize="total", vColor="total", type="value", title="top fatality events", vp=vp_fat)
vp_inj<-viewport(layout.pos.col=1, layout.pos.row=2)
treemap(top_inj_tm, index=c("event_cat","total"), vSize="total", vColor="total", type="value", title="top injure event", vp=vp_inj)
By analysis the events cause most proprety damage and crop damage, FLOOD have biggest impact to economic lost. it caused 38% perproty lost and 15% crop damage. Hurrican or typhoon is second most “costly” event, 22% property damage and 15% agriculture lost.
We don’t combine the value of damage between property and crop, because crop damage is a magnitude level less than property lost. the lost of crop have more impact to overall economy, so it has its own analysis. from this prospective, “DROUGHT” has biggest impact to agriculture.
grid.newpage()
pushViewport(viewport(layout=grid.layout(2,1)))
vp_prop<-viewport(layout.pos.col=1, layout.pos.row=1)
treemap(top_prop_tm, index=c("event_cat","total"), vSize="total", vColor="total", type="value", title="top property damage events", vp=vp_prop)
vp_crop<-viewport(layout.pos.col=1, layout.pos.row=2)
treemap(top_crop_tm, index=c("event_cat","total"), vSize="total", vColor="total", type="value", title="top crop damage events", vp=vp_crop)
The geolocation of states is big factor of what event would be most harmful to public heathly, and would cause the economic lost. Tornado is responsible for lost of life and injure amount lot of in-land state, flodding is common cause in state that receive more rain falls. The HEAT event could happen in both northern and southern state, it’s common “enermy”.
kable(state_tops, "html") %>%
kable_styling(bootstrap_options = c("striped")) %>%
scroll_box(height="500px")
| State | Event Caused Most Fatality | Fatality Count | Event Caused most Injure | Injure Count | Event caused most Property Damage | Damage Value (Million) | Event Caused Most Crop Damage | Damage Value (Million) |
|---|---|---|---|---|---|---|---|---|
| ALABAMA | TORNADO | 342 | TORNADO | 3446 | TORNADO | 5039 | HEAT | 400 |
| ALASKA | AVALANCHE | 33 | ICE STORM | 34 | FLOOD | 167 | HIGH WIND | 0 |
| ARIZONA | FLASH FLOOD | 61 | DUST STORM | 177 | HAIL | 2829 | TROPICAL STORM | 200 |
| ARKANSAS | TORNADO | 100 | TORNADO | 1419 | TORNADO | 1560 | FLOOD | 141 |
| CALIFORNIA | EXCESSIVE HEAT | 110 | WILDFIRE | 978 | FLOOD | 116867 | EXTREME COLD/WIND CHILL | 731 |
| COLORADO | AVALANCHE | 48 | LIGHTNING | 239 | HAIL | 1369 | HAIL | 112 |
| CONNECTICUT | HIGH WIND | 10 | LIGHTNING | 51 | TROPICAL STORM | 60 | HAIL | 0 |
| DELAWARE | EXCESSIVE HEAT | 7 | HIGH SURF | 66 | COASTAL FLOOD | 40 | DROUGHT | 29 |
| FLORIDA | RIP CURRENT | 263 | HURRICANE (TYPHOON) | 812 | HURRICANE (TYPHOON) | 31794 | HURRICANE (TYPHOON) | 1448 |
| GEORGIA | TORNADO | 87 | TORNADO | 1483 | TORNADO | 976 | DROUGHT | 717 |
| GUAM | RIP CURRENT | 38 | HURRICANE (TYPHOON) | 339 | HURRICANE (TYPHOON) | 864 | HURRICANE (TYPHOON) | 106 |
| HAWAII | HIGH SURF | 28 | HIGH SURF | 32 | FLASH FLOOD | 157 | HIGH WIND | 3 |
| IDAHO | AVALANCHE | 16 | THUNDERSTORM WIND | 94 | FLOOD | 114 | HAIL | 6 |
| ILLINOIS | HEAT | 653 | TORNADO | 546 | FLASH FLOOD | 794 | DROUGHT | 285 |
| INDIANA | TORNADO | 34 | TORNADO | 581 | FLOOD | 838 | FLOOD | 697 |
| IOWA | TORNADO | 20 | TORNADO | 441 | FLOOD | 1355 | DROUGHT | 2010 |
| KANSAS | TORNADO | 37 | TORNADO | 454 | TORNADO | 739 | HAIL | 240 |
| KENTUCKY | FLASH FLOOD | 39 | TORNADO | 473 | HAIL | 610 | DROUGHT | 226 |
| LOUISIANA | EXCESSIVE HEAT | 58 | TORNADO | 507 | STORM SURGE/TIDE | 31828 | DROUGHT | 587 |
| MAINE | LIGHTNING | 5 | LIGHTNING | 65 | ICE STORM | 318 | HAIL | 0 |
| MARYLAND | EXCESSIVE HEAT | 88 | EXCESSIVE HEAT | 461 | TROPICAL STORM | 539 | DROUGHT | 100 |
| MASSACHUSETTS | TORNADO | 9 | TORNADO | 424 | TORNADO | 460 | THUNDERSTORM WIND | 1 |
| MICHIGAN | THUNDERSTORM WIND | 27 | HEAT | 315 | THUNDERSTORM WIND | 360 | DROUGHT | 150 |
| MINNESOTA | EXCESSIVE HEAT | 13 | TORNADO | 275 | FLOOD | 1288 | FLOOD | 105 |
| MISSISSIPPI | TORNADO | 64 | TORNADO | 901 | HURRICANE (TYPHOON) | 14178 | HURRICANE (TYPHOON) | 1515 |
| MISSOURI | TORNADO | 233 | EXCESSIVE HEAT | 3525 | TORNADO | 3644 | FLOOD | 596 |
| MONTANA | LIGHTNING | 9 | WILDFIRE | 33 | HAIL | 93 | HAIL | 33 |
| NEBRASKA | WINTER STORM | 11 | TORNADO | 129 | HAIL | 908 | DROUGHT | 720 |
| NEVADA | HEAT | 53 | FLOOD | 51 | FLOOD | 678 | FLOOD | 6 |
| NEW HAMPSHIRE | FLASH FLOOD | 4 | LIGHTNING | 79 | ICE STORM | 65 | FLOOD | 0 |
| NEW JERSEY | EXCESSIVE HEAT | 39 | EXCESSIVE HEAT | 300 | FLOOD | 2112 | DROUGHT | 80 |
| NEW MEXICO | FLASH FLOOD | 16 | TORNADO | 50 | WILDFIRE | 1549 | DROUGHT | 14 |
| NEW YORK | EXCESSIVE HEAT | 93 | THUNDERSTORM WIND | 251 | FLASH FLOOD | 1755 | HAIL | 82 |
| NORTH CAROLINA | TORNADO | 45 | TORNADO | 758 | HURRICANE (TYPHOON) | 5519 | HURRICANE (TYPHOON) | 1457 |
| NORTH DAKOTA | BLIZZARD | 8 | BLIZZARD | 97 | FLOOD | 3907 | THUNDERSTORM WIND | 194 |
| OHIO | FLASH FLOOD | 33 | TORNADO | 285 | FLASH FLOOD | 1230 | DROUGHT | 200 |
| OKLAHOMA | TORNADO | 79 | TORNADO | 1680 | TORNADO | 1752 | DROUGHT | 1097 |
| OREGON | HIGH WIND | 19 | HIGH WIND | 44 | FLOOD | 716 | HAIL | 37 |
| PENNSYLVANIA | EXCESSIVE HEAT | 360 | EXCESSIVE HEAT | 357 | FLASH FLOOD | 1407 | DROUGHT | 539 |
| PUERTO RICO | FLASH FLOOD | 34 | HEAVY RAIN | 10 | HURRICANE (TYPHOON) | 1824 | HURRICANE (TYPHOON) | 451 |
| RHODE ISLAND | HIGH SURF | 3 | LIGHTNING | 17 | FLOOD | 93 | BLIZZARD | 0 |
| SOUTH CAROLINA | EXCESSIVE HEAT | 29 | TORNADO | 263 | ICE STORM | 148 | HURRICANE (TYPHOON) | 20 |
| SOUTH DAKOTA | ICE STORM | 8 | TORNADO | 220 | HAIL | 85 | HAIL | 63 |
| TENNESSEE | TORNADO | 187 | TORNADO | 2159 | FLOOD | 4245 | THUNDERSTORM WIND | 9 |
| TEXAS | EXCESSIVE HEAT | 269 | FLOOD | 6339 | TROPICAL STORM | 5491 | DROUGHT | 6373 |
| UTAH | AVALANCHE | 44 | WINTER STORM | 415 | FLOOD | 332 | HIGH WIND | 2 |
| VERMONT | FLOOD | 4 | THUNDERSTORM WIND | 17 | FLOOD | 1076 | FLASH FLOOD | 15 |
| VIRGIN ISLANDS | HIGH SURF | 3 | LIGHTNING | 1 | HURRICANE (TYPHOON) | 28 | DROUGHT | 0 |
| VIRGINIA | FLASH FLOOD | 29 | TORNADO | 454 | HURRICANE (TYPHOON) | 635 | DROUGHT | 297 |
| WASHINGTON | AVALANCHE | 34 | HIGH WIND | 43 | FLOOD | 212 | FROST/FREEZE | 205 |
| WEST VIRGINIA | FLASH FLOOD | 24 | LIGHTNING | 45 | FLASH FLOOD | 483 | DROUGHT | 20 |
| WISCONSIN | EXCESSIVE HEAT | 94 | TORNADO | 209 | HAIL | 961 | FLOOD | 466 |
| WYOMING | AVALANCHE | 23 | WINTER STORM | 119 | HAIL | 111 | HAIL | 2 |
# for PDF file
#kable(state_tops, "latex", booktabs = T) %>%
# kable_styling(latex_options=c("striped","scale_down"))