Streszczenie

Celem niniejszej analizy jest identyfikacja najbardziej niebezpiecznych zjawisk pogodowych w Stanach Zjednoczonych w latach 1950–2011 na podstawie danych NOAA Storm Database. Analiza skupia się na dwóch aspektach: zagrożeniach dla zdrowia publicznego oraz stratach ekonomicznych. Dane zostały pobrane z oryginalnego pliku CSV w formacie .bz2, a następnie przefiltrowane i przekształcone przy użyciu R. Dla każdego typu zjawiska pogodowego obliczono sumaryczną liczbę ofiar (śmiertelnych i rannych) oraz wysokość strat materialnych. Wyniki zostały zilustrowane za pomocą wykresów słupkowych i tabel. Największe zagrożenie dla zdrowia stanowiły tornada, natomiast największe straty finansowe przyniosły huragany i powodzie. Analiza została opublikowana na platformie RPubs.

Przetwarzanie danych

library(dplyr)
## 
## Dołączanie pakietu: 'dplyr'
## Następujące obiekty zostały zakryte z 'package:stats':
## 
##     filter, lag
## Następujące obiekty zostały zakryte z 'package:base':
## 
##     intersect, setdiff, setequal, union
library(ggplot2)
## Warning: pakiet 'ggplot2' został zbudowany w wersji R 4.3.3
library(readr)
## Warning: pakiet 'readr' został zbudowany w wersji R 4.3.3
data <- read_csv("data_StormData.csv.bz2")
## Rows: 902297 Columns: 37
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (18): BGN_DATE, BGN_TIME, TIME_ZONE, COUNTYNAME, STATE, EVTYPE, BGN_AZI,...
## dbl (18): STATE__, COUNTY, BGN_RANGE, COUNTY_END, END_RANGE, LENGTH, WIDTH, ...
## lgl  (1): COUNTYENDN
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
# sprawdzenie struktury danych
str(data)
## spc_tbl_ [902,297 × 37] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ STATE__   : num [1:902297] 1 1 1 1 1 1 1 1 1 1 ...
##  $ BGN_DATE  : chr [1:902297] "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 [1:902297] "0130" "0145" "1600" "0900" ...
##  $ TIME_ZONE : chr [1:902297] "CST" "CST" "CST" "CST" ...
##  $ COUNTY    : num [1:902297] 97 3 57 89 43 77 9 123 125 57 ...
##  $ COUNTYNAME: chr [1:902297] "MOBILE" "BALDWIN" "FAYETTE" "MADISON" ...
##  $ STATE     : chr [1:902297] "AL" "AL" "AL" "AL" ...
##  $ EVTYPE    : chr [1:902297] "TORNADO" "TORNADO" "TORNADO" "TORNADO" ...
##  $ BGN_RANGE : num [1:902297] 0 0 0 0 0 0 0 0 0 0 ...
##  $ BGN_AZI   : chr [1:902297] NA NA NA NA ...
##  $ BGN_LOCATI: chr [1:902297] NA NA NA NA ...
##  $ END_DATE  : chr [1:902297] NA NA NA NA ...
##  $ END_TIME  : chr [1:902297] NA NA NA NA ...
##  $ COUNTY_END: num [1:902297] 0 0 0 0 0 0 0 0 0 0 ...
##  $ COUNTYENDN: logi [1:902297] NA NA NA NA NA NA ...
##  $ END_RANGE : num [1:902297] 0 0 0 0 0 0 0 0 0 0 ...
##  $ END_AZI   : chr [1:902297] NA NA NA NA ...
##  $ END_LOCATI: chr [1:902297] NA NA NA NA ...
##  $ LENGTH    : num [1:902297] 14 2 0.1 0 0 1.5 1.5 0 3.3 2.3 ...
##  $ WIDTH     : num [1:902297] 100 150 123 100 150 177 33 33 100 100 ...
##  $ F         : num [1:902297] 3 2 2 2 2 2 2 1 3 3 ...
##  $ MAG       : num [1:902297] 0 0 0 0 0 0 0 0 0 0 ...
##  $ FATALITIES: num [1:902297] 0 0 0 0 0 0 0 0 1 0 ...
##  $ INJURIES  : num [1:902297] 15 0 2 2 2 6 1 0 14 0 ...
##  $ PROPDMG   : num [1:902297] 25 2.5 25 2.5 2.5 2.5 2.5 2.5 25 25 ...
##  $ PROPDMGEXP: chr [1:902297] "K" "K" "K" "K" ...
##  $ CROPDMG   : num [1:902297] 0 0 0 0 0 0 0 0 0 0 ...
##  $ CROPDMGEXP: chr [1:902297] NA NA NA NA ...
##  $ WFO       : chr [1:902297] NA NA NA NA ...
##  $ STATEOFFIC: chr [1:902297] NA NA NA NA ...
##  $ ZONENAMES : chr [1:902297] NA NA NA NA ...
##  $ LATITUDE  : num [1:902297] 3040 3042 3340 3458 3412 ...
##  $ LONGITUDE : num [1:902297] 8812 8755 8742 8626 8642 ...
##  $ LATITUDE_E: num [1:902297] 3051 0 0 0 0 ...
##  $ LONGITUDE_: num [1:902297] 8806 0 0 0 0 ...
##  $ REMARKS   : chr [1:902297] NA NA NA NA ...
##  $ REFNUM    : num [1:902297] 1 2 3 4 5 6 7 8 9 10 ...
##  - attr(*, "spec")=
##   .. cols(
##   ..   STATE__ = col_double(),
##   ..   BGN_DATE = col_character(),
##   ..   BGN_TIME = col_character(),
##   ..   TIME_ZONE = col_character(),
##   ..   COUNTY = col_double(),
##   ..   COUNTYNAME = col_character(),
##   ..   STATE = col_character(),
##   ..   EVTYPE = col_character(),
##   ..   BGN_RANGE = col_double(),
##   ..   BGN_AZI = col_character(),
##   ..   BGN_LOCATI = col_character(),
##   ..   END_DATE = col_character(),
##   ..   END_TIME = col_character(),
##   ..   COUNTY_END = col_double(),
##   ..   COUNTYENDN = col_logical(),
##   ..   END_RANGE = col_double(),
##   ..   END_AZI = col_character(),
##   ..   END_LOCATI = col_character(),
##   ..   LENGTH = col_double(),
##   ..   WIDTH = col_double(),
##   ..   F = col_double(),
##   ..   MAG = col_double(),
##   ..   FATALITIES = col_double(),
##   ..   INJURIES = col_double(),
##   ..   PROPDMG = col_double(),
##   ..   PROPDMGEXP = col_character(),
##   ..   CROPDMG = col_double(),
##   ..   CROPDMGEXP = col_character(),
##   ..   WFO = col_character(),
##   ..   STATEOFFIC = col_character(),
##   ..   ZONENAMES = col_character(),
##   ..   LATITUDE = col_double(),
##   ..   LONGITUDE = col_double(),
##   ..   LATITUDE_E = col_double(),
##   ..   LONGITUDE_ = col_double(),
##   ..   REMARKS = col_character(),
##   ..   REFNUM = col_double()
##   .. )
##  - attr(*, "problems")=<externalptr>
# wybor kolumn istotnych dla analizy 
storm <- data %>%
  select(EVTYPE, FATALITIES, INJURIES, PROPDMG, PROPDMGEXP, CROPDMG, CROPDMGEXP)

# przeliczanie wartosci z sufixem exp -> aby moc obliczyc faktyczne straty 
convert_exp <- function(value, exp) {
  exp <- toupper(exp)
  multiplier <- case_when(
    exp == "K" ~ 1e3,
    exp == "M" ~ 1e6,
    exp == "B" ~ 1e9,
    exp %in% c("", "+", "-", "?") ~ 1,
    TRUE ~ 0
  )
  return(value * multiplier)
}

# obliczanie lacznych strat i wplywu na zdrowie
storm <- storm %>%
  mutate(
    PROPDMGVAL = convert_exp(PROPDMG, PROPDMGEXP),
    CROPDMGVAL = convert_exp(CROPDMG, CROPDMGEXP),
    TOTALDMG = PROPDMGVAL + CROPDMGVAL,
    HEALTH_IMPACT = FATALITIES + INJURIES
  )

Wyniki

1. Najbardziej szkodliwe zjawiska pogodowe dla zdrowia

health_impact <- storm %>%
  group_by(EVTYPE) %>%
  summarise(Total_Health_Impact = sum(HEALTH_IMPACT, na.rm = TRUE)) %>%
  arrange(desc(Total_Health_Impact)) %>%
  slice_head(n = 10)

ggplot(health_impact, aes(x = reorder(EVTYPE, Total_Health_Impact), y = Total_Health_Impact)) +
  geom_col(fill = "firebrick") +
  coord_flip() +
  labs(title = "10 najbardziej szkodliwych zjawisk pogodowych dla zdrowia (1950–2011)",
       x = "Typ zjawiska", y = "Łączna liczba ofiar (rannych i zmarłych)") +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    plot.title.position = "plot",
    plot.margin = margin(t = 30, r = 20, b = 20, l = 20)
  )

2. Największe straty ekonomiczne wg typu zjawiska

economic_impact <- storm %>%
  group_by(EVTYPE) %>%
  summarise(Total_Damage = sum(TOTALDMG, na.rm = TRUE)) %>%
  arrange(desc(Total_Damage)) %>%
  slice_head(n = 10)

ggplot(economic_impact, aes(x = reorder(EVTYPE, Total_Damage), y = Total_Damage / 1e9)) +
  geom_col(fill = "darkblue") +
  coord_flip() +
  labs(title = "10 zjawisk powodujących największe straty ekonomiczne (1950–2011)",
       x = "Typ zjawiska", y = "Łączne straty (mld USD)") +
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
    plot.title.position = "plot",
    plot.margin = margin(t = 30, r = 20, b = 20, l = 20)
  )

## Czy ten wynik ma sens? ZDROWIE PUBLICZNE

Tornada są najbardziej szkodliwe — zgodne z rzeczywistością, bo powodują bardzo szybkie i silne zniszczenia, często bez dużego czasu na ewakuację.

Upały (Excessive Heat) również istotne — wpływają szczególnie na osoby starsze i osoby z chorobami serca.

STRATY EKONOMICZNE

Powodzie (Flood) prowadzą do największych szkód ekonomicznych, co także ma potwierdzenie w danych historycznych — zalewają miasta, infrastrukturę i rolnictwo.

Huragany i sztormy jako kolejne źródła ogromnych strat, co obserwujemy głównie w regionach przybrzeżnych.

Uwagi końcowe

Dalsza analiza mogłaby obejmować standaryzację nazw zdarzeń w kolumnie EVTYPE oraz analizę przestrzenną rozkładu zdarzeń. Dane mogą być również filtrowane pod kątem lat, aby przeanalizować trendy czasowe.