Że czwarta fala szaleje to nadmiarowe zgony w Europie sobie liczę, w której to kategorii Polska cytując poetę trzecie miejsce w świecie (Kazik Staszewski/Amnezja)
Dane pobieram za pomocą get_eurostat
(pakiet eurostat
):
library("eurostat") # demo_r_mwk_ts = Deaths by week and sex z <- get_eurostat("demo_r_mwk_ts", stringsAsFactors = FALSE) %>% mutate (time = as.character(time)) %>% mutate (year = as.numeric(substr(time, 1, 4)), week = as.numeric(substr(time, 6,7)), sex = as.factor(sex), geo = as.factor(geo)) %>% select (sex, geo, year, week, value=values) %>% filter (sex == 'T')
Końcowy filter
usuwa liczbę zgonów dla kobiet/mężczyzn osobno, bo chcemy tylko analizować ogółem czyli Total.
W pliku ecdc_countries_names_codes3166.csv
są nazwy krajów (bo w bazie Eurostatu są tylko ISO-kody):
## country names nn <- read.csv("ecdc_countries_names_codes3166.csv", sep = ';', header=T, na.string="NA" )
Teraz liczę 5-letnie średnie dla okresu przed pandemią czyli dla lat 2015--2019 włącznie:
## mean weekly deaths 2015--2019 z0 <- z %>% filter ( year >= 2015 & year < 2020) %>% group_by(geo, week) %>% summarise (d0 = mean(value, na.rm=T))
Oraz tygodniowe liczby zgonów dla lat 2020--2021
## weekly deaths 2020--2021 z1 <- z %>% filter ( year > 2019 ) %>% group_by(geo, year, week) %>% summarise ( d1 = sum(value))
Łączę z0
z z1
; liczę różnice między zgonami 2020--2021 a średnimi. Najpierw usuwam wiersze z NA w kolumnach zawierających zgony/średnie (drop_na
). To w szczegolności usunie wiersze z tygodni (w roku 2021), dla których jeszcze nie ma danych.
## join z0 z1 and compute differences zz <- left_join(z0, z1, by=c("week", "geo")) %>% drop_na(d0,d1) %>% mutate (exp = (d1 - d0)/d0 * 100, exm = d1 - d0 ) zz <- left_join(zz, nn, by=c('geo'='id'))
Osobno liczę numer ostatniego raportowanego tygodnia w roku 2021. Pytanie o numer ostatniego w ogóle jest bez sensu, bo w 2020 będzie to ostatni tydzień. Ten fragment ciut mało robust jest bo w 2022 trzeba go będzie zmodyfikować
## if NA then the country stop reporting in 2020 zz.last.week <- zz %>% filter (year == 2021) %>% group_by (geo) %>% summarise (lw = last(week)) %>% drop_na(lw) ## najbardziej aktualny raportowany tydzień (różne kraje raportują różnie) latestweek <- max (zz.last.week$lw)
Uwaga: niektóre kraje nie raportują w 2021, więc ich nie będzie w ramce zz.last.week
z uwagi na filter
.
Ramka zzt
zawiera sumy różnic; bezwzględne (exm
) oraz względne w procentach względem poziomu średniego 2015--2019 (exp
):
### total exmort zzt <- zz %>% group_by(geo) %>% summarise(country=last(country), exm = sum(exm), nm = sum(d0)) %>% mutate (exmp = exm/nm * 100)
Dodajemy informację z ramki zz.last.week
; jeżeli w tej ramce nie ma kraju (bo nie raportował w 2021) to usuwamy go (drop_na(lw)
). Wypierniczamy kraje raportujące więcej niż 6 tygodni po kraju (krajach), który przysłały raport najpóźniej. Np jak jakiś kraj-prymus dostarczył w 47 tygodniu to tylko kraje raportujące z tygodni 41 i później zostają a inne są usuwane (jako nieporównywalne)
zztt <- left_join(zzt, zz.last.week, by='geo') %>% drop_na(lw) %>% filter (lw >= latestweek - 6) ## ile zostało krajów (dla ciekawości): countries.left <- nrow(zztt)
Wykres słupkowy względnej nadmiarowej umieralności (Total excess mortality by country) Trochę go komplikujemy bo słupek PL ma być wyróżniony (w tym celu tworzymy zmienną base
a potem ręcznie ustawiamy legendę scale_fill_manual
):
p6 <- zztt %>% mutate( base=ifelse(geo=='PL', "1", "0")) %>% ggplot(aes(x = reorder(country, exmp ), fill=as.factor(base))) + geom_bar(aes(y = exmp), stat="identity", alpha=.4 ) + geom_text(aes(label=sprintf("%.1f", exmp), y= exmp ), vjust=0.25, hjust=1.25, size=2, color='black' ) + geom_text(aes(label=sprintf("%.0f", lw), y= 0 ), vjust=0.25, hjust=-1.25, size=2, color='brown4' ) + xlab(label="") + ylab(label="") + ggtitle("Total Excessive deaths in Europe 2020--2021", subtitle ="Sum of (deaths_2020/2021 - average_2015--2019) / average_2015--2019 * 100%") + theme_nikw() + coord_flip() + scale_fill_manual( values = c( "1"="red", "0"="steelblue" ), guide = FALSE ) + labs(caption=x.note)
Wykres dynamiki. Ponieważ krajów jest dużo to usuwamy (pierwszy filter
) `nieciekawe' (małe lub te które mają jakiś feler, np dane niepełne);
p7 <- zz %>% filter (! geo %in% c('AL', 'AM', 'IE', 'IS', 'UK', 'CY', 'GE', 'LI', 'ME')) %>% mutate(date= as.Date(sprintf("%i-%i-1", year, week), "%Y-%U-%u") ) %>% ##ggplot(aes(x = date, y =exp, group=geo, color=geo )) + ggplot(aes(x = date, y =exp)) + facet_wrap( ~country, scales = "fixed", ncol = 4, shrink = F) + geom_point(size=.4) + geom_smooth(method="loess", size=1, se = F, color="red", span =.25) + geom_hline(yintercept = 50, color="firebrick", alpha=.2, size=1) + scale_y_continuous(breaks=seq(-100, 200, by=50)) + coord_cartesian(ylim = c(-100, 200)) + ggtitle("Excessive deaths in Europe 2020--2021", subtitle ="(deaths_2020/2021 - average_2015--2019) / average_2015--2019 * 100%") + theme_nikw() + xlab(label="%") + labs(caption=note)
Teraz wszystko na jednym ale ponieważ krajów jest za dużo (w sensie za mało byłoby kolorów żeby wykres był czytelny), to dzielimy je na dwie grupy: Polska i reszta. Każda grupa innym kolorem:
p8 <- zz %>% filter (! geo %in% c('AL', 'AM', 'IE', 'IS', 'UK', 'CY', 'GE', 'LI', 'ME')) %>% mutate( base=ifelse(geo=='PL', "1", "0")) %>% mutate(date= as.Date(sprintf("%i-%i-1", year, week), "%Y-%U-%u") ) %>% ggplot(aes(x = date, y =exp, color=as.factor(base ))) + ##ggplot(aes(x = date, y =exp)) + geom_point(size=.4) + geom_smooth(aes(x = date, y =exp, group=geo), method="loess", size=.3, se = F, span =.25) + geom_hline(yintercept = 50, color="firebrick", alpha=.2, size=1) + coord_cartesian(ylim = c(-100, 200)) + scale_color_manual( values = c( "1"="red", "0"="steelblue" ), guide = FALSE ) + theme_nikw() + ylab(label="%") + ggtitle("Excessive deaths in Europe 2020--2021 and Poland (red)", subtitle ="(deaths_2020/2021 - average_2015--2019) / average_2015--2019 * 100%") + scale_y_continuous(breaks=seq(-100, 200, by=50)) + labs(caption=note)
Wszystko działa (i koliduje jak mówił Bolec), bo działało na PC, ale był problem na raspberry, na którym to ostatecznie ma być uruchamiane z automatu co dwa tygodnie. Bo tam Debian starszy (Buster) i na arma. Zapodanie:
install.package("eurostat")
Skutkowało pobraniem wielu pakietów i błędem przy kompilacji czegoś co się nazywało s2
. Kombinowałem na różne sposoby jak to skompilować bo stosownego pakietu w Debianie nie było. Ni-chu-chu.
W przypływie olśnienia obejrzałem zależności tego eurostatu
, wśród których żadnego s2
nie było. Był za to sf
, które z kolei rzekomo zależał od s2
. Żeby było śmieszniej sf
dało się zainstalować (mimo że s2
nie było -- stąd rzekomo):
apt install r-cran-sf/oldstable
Problem się rozwiązał...
Skrypt będzie się uruchamiał co dwa tygodnie. Generował rysunki i wysyłał je na twittera
Całość jest na githubie i to w dodatku jako plik Rmd
, ale nie na moim koncie tylko na koncie Koła Naukowego SM w PSW w Kwidzynie, którego póki co jestem opiekunem i jedynym członkiem w jednym (por. github.com/knsm-psw/ES-mortality)
Podobają mi się treści jakie tutaj znalazłam.
OdpowiedzUsuń