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", 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)"
)
Natural events that cause most fatality and injures are considered most harmful, in United States excesive heat caused most fatality.
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)
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)
xtab<-xtable(state_tops)
print(xtab, type="html")
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) | |
---|---|---|---|---|---|---|---|---|---|
1 | ALABAMA | TORNADO | 342.00 | TORNADO | 3446.00 | TORNADO | 5039.00 | HEAT | 400.00 |
2 | ALASKA | AVALANCHE | 33.00 | ICE STORM | 34.00 | FLOOD | 167.00 | HIGH WIND | 0.00 |
3 | ARIZONA | FLASH FLOOD | 61.00 | DUST STORM | 177.00 | HAIL | 2829.00 | TROPICAL STORM | 200.00 |
4 | ARKANSAS | TORNADO | 100.00 | TORNADO | 1419.00 | TORNADO | 1560.00 | FLOOD | 141.00 |
5 | CALIFORNIA | EXCESSIVE HEAT | 110.00 | WILDFIRE | 978.00 | FLOOD | 116867.00 | EXTREME COLD/WIND CHILL | 731.00 |
6 | COLORADO | AVALANCHE | 48.00 | LIGHTNING | 239.00 | HAIL | 1369.00 | HAIL | 112.00 |
7 | CONNECTICUT | HIGH WIND | 10.00 | LIGHTNING | 51.00 | TROPICAL STORM | 60.00 | HAIL | 0.00 |
8 | DELAWARE | EXCESSIVE HEAT | 7.00 | HIGH SURF | 66.00 | COASTAL FLOOD | 40.00 | DROUGHT | 29.00 |
9 | FLORIDA | RIP CURRENT | 263.00 | HURRICANE (TYPHOON) | 812.00 | HURRICANE (TYPHOON) | 31794.00 | HURRICANE (TYPHOON) | 1448.00 |
10 | GEORGIA | TORNADO | 87.00 | TORNADO | 1483.00 | TORNADO | 976.00 | DROUGHT | 717.00 |
11 | GUAM | RIP CURRENT | 38.00 | HURRICANE (TYPHOON) | 339.00 | HURRICANE (TYPHOON) | 864.00 | HURRICANE (TYPHOON) | 106.00 |
12 | HAWAII | HIGH SURF | 28.00 | HIGH SURF | 32.00 | FLASH FLOOD | 157.00 | HIGH WIND | 3.00 |
13 | IDAHO | AVALANCHE | 16.00 | THUNDERSTORM WIND | 94.00 | FLOOD | 114.00 | HAIL | 6.00 |
14 | ILLINOIS | HEAT | 653.00 | TORNADO | 546.00 | FLASH FLOOD | 794.00 | DROUGHT | 285.00 |
15 | INDIANA | TORNADO | 34.00 | TORNADO | 581.00 | FLOOD | 838.00 | FLOOD | 697.00 |
16 | IOWA | TORNADO | 20.00 | TORNADO | 441.00 | FLOOD | 1355.00 | DROUGHT | 2010.00 |
17 | KANSAS | TORNADO | 37.00 | TORNADO | 454.00 | TORNADO | 739.00 | HAIL | 240.00 |
18 | KENTUCKY | FLASH FLOOD | 39.00 | TORNADO | 473.00 | HAIL | 610.00 | DROUGHT | 226.00 |
19 | LOUISIANA | EXCESSIVE HEAT | 58.00 | TORNADO | 507.00 | STORM SURGE/TIDE | 31828.00 | DROUGHT | 587.00 |
20 | MAINE | LIGHTNING | 5.00 | LIGHTNING | 65.00 | ICE STORM | 318.00 | HAIL | 0.00 |
21 | MARYLAND | EXCESSIVE HEAT | 88.00 | EXCESSIVE HEAT | 461.00 | TROPICAL STORM | 539.00 | DROUGHT | 100.00 |
22 | MASSACHUSETTS | TORNADO | 9.00 | TORNADO | 424.00 | TORNADO | 460.00 | THUNDERSTORM WIND | 1.00 |
23 | MICHIGAN | THUNDERSTORM WIND | 27.00 | HEAT | 315.00 | THUNDERSTORM WIND | 360.00 | DROUGHT | 150.00 |
24 | MINNESOTA | EXCESSIVE HEAT | 13.00 | TORNADO | 275.00 | FLOOD | 1288.00 | FLOOD | 105.00 |
25 | MISSISSIPPI | TORNADO | 64.00 | TORNADO | 901.00 | HURRICANE (TYPHOON) | 14178.00 | HURRICANE (TYPHOON) | 1515.00 |
26 | MISSOURI | TORNADO | 233.00 | EXCESSIVE HEAT | 3525.00 | TORNADO | 3644.00 | FLOOD | 596.00 |
27 | MONTANA | LIGHTNING | 9.00 | WILDFIRE | 33.00 | HAIL | 93.00 | HAIL | 33.00 |
28 | NEBRASKA | WINTER STORM | 11.00 | TORNADO | 129.00 | HAIL | 908.00 | DROUGHT | 720.00 |
29 | NEVADA | HEAT | 53.00 | FLOOD | 51.00 | FLOOD | 678.00 | FLOOD | 6.00 |
30 | NEW HAMPSHIRE | FLASH FLOOD | 4.00 | LIGHTNING | 79.00 | ICE STORM | 65.00 | FLOOD | 0.00 |
31 | NEW JERSEY | EXCESSIVE HEAT | 39.00 | EXCESSIVE HEAT | 300.00 | FLOOD | 2112.00 | DROUGHT | 80.00 |
32 | NEW MEXICO | FLASH FLOOD | 16.00 | TORNADO | 50.00 | WILDFIRE | 1549.00 | DROUGHT | 14.00 |
33 | NEW YORK | EXCESSIVE HEAT | 93.00 | THUNDERSTORM WIND | 251.00 | FLASH FLOOD | 1755.00 | HAIL | 82.00 |
34 | NORTH CAROLINA | TORNADO | 45.00 | TORNADO | 758.00 | HURRICANE (TYPHOON) | 5519.00 | HURRICANE (TYPHOON) | 1457.00 |
35 | NORTH DAKOTA | BLIZZARD | 8.00 | BLIZZARD | 97.00 | FLOOD | 3907.00 | THUNDERSTORM WIND | 194.00 |
36 | OHIO | FLASH FLOOD | 33.00 | TORNADO | 285.00 | FLASH FLOOD | 1230.00 | DROUGHT | 200.00 |
37 | OKLAHOMA | TORNADO | 79.00 | TORNADO | 1680.00 | TORNADO | 1752.00 | DROUGHT | 1097.00 |
38 | OREGON | HIGH WIND | 19.00 | HIGH WIND | 44.00 | FLOOD | 716.00 | HAIL | 37.00 |
39 | PENNSYLVANIA | EXCESSIVE HEAT | 360.00 | EXCESSIVE HEAT | 357.00 | FLASH FLOOD | 1407.00 | DROUGHT | 539.00 |
40 | PUERTO RICO | FLASH FLOOD | 34.00 | HEAVY RAIN | 10.00 | HURRICANE (TYPHOON) | 1824.00 | HURRICANE (TYPHOON) | 451.00 |
41 | RHODE ISLAND | HIGH SURF | 3.00 | LIGHTNING | 17.00 | FLOOD | 93.00 | BLIZZARD | 0.00 |
42 | SOUTH CAROLINA | EXCESSIVE HEAT | 29.00 | TORNADO | 263.00 | ICE STORM | 148.00 | HURRICANE (TYPHOON) | 20.00 |
43 | SOUTH DAKOTA | ICE STORM | 8.00 | TORNADO | 220.00 | HAIL | 85.00 | HAIL | 63.00 |
44 | TENNESSEE | TORNADO | 187.00 | TORNADO | 2159.00 | FLOOD | 4245.00 | THUNDERSTORM WIND | 9.00 |
45 | TEXAS | EXCESSIVE HEAT | 269.00 | FLOOD | 6339.00 | TROPICAL STORM | 5491.00 | DROUGHT | 6373.00 |
46 | UTAH | AVALANCHE | 44.00 | WINTER STORM | 415.00 | FLOOD | 332.00 | HIGH WIND | 2.00 |
47 | VERMONT | FLOOD | 4.00 | THUNDERSTORM WIND | 17.00 | FLOOD | 1076.00 | FLASH FLOOD | 15.00 |
48 | VIRGIN ISLANDS | HIGH SURF | 3.00 | LIGHTNING | 1.00 | HURRICANE (TYPHOON) | 28.00 | DROUGHT | 0.00 |
49 | VIRGINIA | FLASH FLOOD | 29.00 | TORNADO | 454.00 | HURRICANE (TYPHOON) | 635.00 | DROUGHT | 297.00 |
50 | WASHINGTON | AVALANCHE | 34.00 | HIGH WIND | 43.00 | FLOOD | 212.00 | FROST/FREEZE | 205.00 |
51 | WEST VIRGINIA | FLASH FLOOD | 24.00 | LIGHTNING | 45.00 | FLASH FLOOD | 483.00 | DROUGHT | 20.00 |
52 | WISCONSIN | EXCESSIVE HEAT | 94.00 | TORNADO | 209.00 | HAIL | 961.00 | FLOOD | 466.00 |
53 | WYOMING | AVALANCHE | 23.00 | WINTER STORM | 119.00 | HAIL | 111.00 | HAIL | 2.00 |