library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(ggplot2)
library(GGally)
library(car)
## Loading required package: carData
##
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
##
## recode
library(olsrr)
##
## Attaching package: 'olsrr'
## The following object is masked from 'package:datasets':
##
## rivers
library(janitor) # pridáme na čistenie názvov stĺpcov
##
## Attaching package: 'janitor'
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
covid <- read.csv("covid_africa.csv",
stringsAsFactors = FALSE,
check.names = FALSE) # aby nám R nemenil názvy stĺpcov
# vyčistíme názvy stĺpcov -> bez medzier, lomiek, veľkých písmen
covid <- janitor::clean_names(covid)
# pozrieme názvy stĺpcov, aby sme vedeli, s čím robíme
names(covid)
## [1] "country_other" "total_cases" "total_deaths" "total_recovered"
## [5] "active_cases" "tot_cases_1m_pop" "deaths_1m_pop" "total_tests"
## [9] "tests_1m_pop" "population"
# prvé riadky
head(covid)
## country_other total_cases total_deaths total_recovered active_cases
## 1 Algeria 271852 6881 183061 81910
## 2 Angola 105384 1934 103419 31
## 3 Benin 28014 163 27847 4
## 4 Botswana 330256 2801 327049 406
## 5 Burkina Faso 22056 396 21596 64
## 6 Burundi 54241 38 53569 634
## tot_cases_1m_pop deaths_1m_pop total_tests tests_1m_pop population
## 1 5995 152 230960 5093 45350148
## 2 3009 55 1499795 42818 35027343
## 3 2191 13 604310 47268 12784726
## 4 135286 1147 2026898 830300 2441162
## 5 998 18 248995 11265 22102838
## 6 4296 3 345742 27386 12624840
# štruktúra
str(covid)
## 'data.frame': 54 obs. of 10 variables:
## $ country_other : chr "Algeria" "Angola" "Benin" "Botswana" ...
## $ total_cases : int 271852 105384 28014 330256 22056 54241 15368 64238 125090 7701 ...
## $ total_deaths : int 6881 1934 163 2801 396 38 113 415 1974 194 ...
## $ total_recovered : num 183061 103419 27847 327049 21596 ...
## $ active_cases : num 81910 31 4 406 64 ...
## $ tot_cases_1m_pop: int 5995 3009 2191 135286 998 4296 3063 113159 4482 442 ...
## $ deaths_1m_pop : int 152 55 13 1147 18 3 23 731 71 11 ...
## $ total_tests : num 230960 1499795 604310 2026898 248995 ...
## $ tests_1m_pop : num 5093 42818 47268 830300 11265 ...
## $ population : int 45350148 35027343 12784726 2441162 22102838 12624840 5016678 567678 27911548 17413580 ...
# základná štatistika
summary(covid)
## country_other total_cases total_deaths total_recovered
## Length:54 Min. : 6597 Min. : 38.0 Min. : 4874
## Class :character 1st Qu.: 22886 1st Qu.: 291.2 1st Qu.: 19856
## Mode :character Median : 63854 Median : 1024.0 Median : 62471
## Mean : 227909 Mean : 4772.6 Mean : 206895
## 3rd Qu.: 171956 3rd Qu.: 3066.5 3rd Qu.: 168677
## Max. :4076463 Max. :102595.0 Max. :3912506
## NA's :3
## active_cases tot_cases_1m_pop deaths_1m_pop total_tests
## Min. : 0 Min. : 381 Min. : 3.00 Min. : 23693
## 1st Qu.: 27 1st Qu.: 2452 1st Qu.: 33.25 1st Qu.: 346778
## Median : 309 Median : 4760 Median : 93.50 Median : 804909
## Mean : 6351 Mean : 27020 Mean : 312.44 Mean : 2142069
## 3rd Qu.: 1752 3rd Qu.: 16997 3rd Qu.: 226.25 3rd Qu.: 2255373
## Max. :81910 Max. :512311 Max. :2442.00 Max. :26795090
## NA's :3 NA's :3
## tests_1m_pop population
## Min. : 5093 Min. : 99426
## 1st Qu.: 29172 1st Qu.: 2890966
## Median : 60951 Median : 13733078
## Mean :167376 Mean : 26016706
## 3rd Qu.:227793 3rd Qu.: 31591107
## Max. :885119 Max. :216746934
## NA's :3
## 2️⃣ Výber a premenovanie premenných – opravný chunk
covid_small <- covid %>%
select(
country = country_other,
total_cases = total_cases,
total_deaths = total_deaths,
total_rec = total_recovered,
active = active_cases,
cases_1m = tot_cases_1m_pop,
deaths_1m = deaths_1m_pop,
total_tests = total_tests,
tests_1m = tests_1m_pop,
population = population
)
# odstránime riadky s NA v premenných, ktoré budeme používať v modeli
covid_small <- covid_small %>%
filter(
!is.na(deaths_1m),
!is.na(cases_1m),
!is.na(tests_1m),
!is.na(total_tests),
!is.na(total_cases)
)
dim(covid_small)
## [1] 51 10
summary(covid_small)
## country total_cases total_deaths total_rec
## Length:51 Min. : 6597 Min. : 38 Min. : 4874
## Class :character 1st Qu.: 23716 1st Qu.: 301 1st Qu.: 21596
## Mode :character Median : 64238 Median : 1361 Median : 63755
## Mean : 239293 Mean : 5030 Mean : 214121
## 3rd Qu.: 202708 3rd Qu.: 3394 3rd Qu.: 170255
## Max. :4076463 Max. :102595 Max. :3912506
## NA's :2
## active cases_1m deaths_1m total_tests
## Min. : 0 Min. : 381 Min. : 3.0 Min. : 23693
## 1st Qu.: 43 1st Qu.: 2562 1st Qu.: 33.5 1st Qu.: 346778
## Median : 338 Median : 4659 Median : 86.0 Median : 804909
## Mean : 6610 Mean : 18354 Mean : 293.2 Mean : 2142069
## 3rd Qu.: 2369 3rd Qu.: 16662 3rd Qu.: 220.5 3rd Qu.: 2255373
## Max. :81910 Max. :135286 Max. :2442.0 Max. :26795090
## NA's :2
## tests_1m population
## Min. : 5093 Min. : 227679
## 1st Qu.: 29172 1st Qu.: 4282112
## Median : 60951 Median : 13865691
## Mean :167376 Mean : 26286211
## 3rd Qu.:227793 3rd Qu.: 30786764
## Max. :885119 Max. :216746934
##
vars_for_corr <- covid_small %>%
select(deaths_1m, cases_1m, tests_1m, total_cases, total_tests, population)
cor_matrix <- cor(vars_for_corr)
round(cor_matrix, 2)
## deaths_1m cases_1m tests_1m total_cases total_tests population
## deaths_1m 1.00 0.84 0.66 0.56 0.43 -0.14
## cases_1m 0.84 1.00 0.83 0.37 0.27 -0.21
## tests_1m 0.66 0.83 1.00 0.26 0.25 -0.27
## total_cases 0.56 0.37 0.26 1.00 0.95 0.23
## total_tests 0.43 0.27 0.25 0.95 1.00 0.34
## population -0.14 -0.21 -0.27 0.23 0.34 1.00
Korelačná matica odhalila veľmi silnú multikolinearitu medzi premennými total_cases a total_tests (r = 0.95), ako aj medzi cases_1m a tests_1m (r = 0.83). Tieto páry premenných sú takmer lineárne závislé, čo môže v regresných modeloch viesť k nafúknutým štandardným chybám a nestabilným odhadom koeficientov. Populácia má voči ostatným premenným iba slabé korelácie a nepredstavuje riziko multikolinearity.
model_full <- lm(
deaths_1m ~ cases_1m + tests_1m + total_cases + total_tests + population,
data = covid_small
)
summary(model_full)
##
## Call:
## lm(formula = deaths_1m ~ cases_1m + tests_1m + total_cases +
## total_tests + population, data = covid_small)
##
## Residuals:
## Min 1Q Median 3Q Max
## -595.49 -54.55 -21.71 14.22 851.22
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.933e+01 5.140e+01 0.960 0.342358
## cases_1m 9.279e-03 2.461e-03 3.771 0.000472 ***
## tests_1m 2.942e-04 3.321e-04 0.886 0.380330
## total_cases 8.311e-04 2.414e-04 3.443 0.001254 **
## total_tests -8.631e-05 3.530e-05 -2.445 0.018465 *
## population 3.914e-07 1.103e-06 0.355 0.724324
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 233.1 on 45 degrees of freedom
## Multiple R-squared: 0.8059, Adjusted R-squared: 0.7844
## F-statistic: 37.38 on 5 and 45 DF, p-value: 6.088e-15
Model má vysokú vysvetľovaciu schopnosť (R² = 0.81), avšak pri interpretácii jednotlivých koeficientov vidíme typické prejavy multikolinearity. Premenné total_cases a total_tests sú extrémne silno korelované (r = 0.95), rovnako ako cases_1m a tests_1m (r = 0.83). V dôsledku toho sa niektoré premenné stávajú nevýznamné (tests_1m), hoci by teoreticky významné byť mali, a iné nadobúdajú koeficienty s neintuitívnym znamienkom (total_tests). Preto je vhodné model zjednodušiť odstránením vysoko korelovaných premenných a overiť VIF a condition index.
car::vif(model_full)
## cases_1m tests_1m total_cases total_tests population
## 5.190946 5.005485 19.584466 20.170923 1.615005
Výsledky VIF testu jasne ukazujú veľmi silnú multikolinearitu medzi premennými total_cases a total_tests, ktoré majú VIF hodnoty približne 20. To znamená, že tieto premenné sú takmer lineárne závislé, čo spôsobuje nestabilitu odhadov v regresnom modeli. Premenné cases_1m a tests_1m majú VIF približne 5, čo poukazuje na strednú multikolinearitu a vysvetľuje, prečo tests_1m vychádza ako štatisticky nevýznamná. Premenná population má nízky VIF, takže nespôsobuje multikolinearitu. Z hľadiska kvality modelu je vhodné odstrániť aspoň jednu z dvojíc silno korelovaných premenných (total_cases, total_tests) a znovu model prepočítať.
olsrr::ols_eigen_cindex(model_full)
## Eigenvalue Condition Index intercept cases_1m tests_1m total_cases
## 1 3.49817334 1.000000 0.0189844847 0.0069333011 0.0063783281 0.002347474
## 2 1.20026057 1.707194 0.0005583525 0.0300160705 0.0278757041 0.003140289
## 3 0.89208487 1.980239 0.1476845595 0.0009207618 0.0002663169 0.012497376
## 4 0.26715281 3.618602 0.7088717446 0.0776757411 0.0065455914 0.002752964
## 5 0.12384331 5.314769 0.1194130348 0.4035076715 0.4839976781 0.019479987
## 6 0.01848509 13.756563 0.0044878238 0.4809464541 0.4749363812 0.959781909
## total_tests population
## 1 0.002305803 0.011165937
## 2 0.003841095 0.095097028
## 3 0.005720336 0.131415539
## 4 0.002002245 0.527075911
## 5 0.024781571 0.003608377
## 6 0.961348950 0.231637209
model_reduced <- lm(
deaths_1m ~ cases_1m + tests_1m + population,
data = covid_small
)
summary(model_reduced)
##
## Call:
## lm(formula = deaths_1m ~ cases_1m + tests_1m + population, data = covid_small)
##
## Residuals:
## Min 1Q Median 3Q Max
## -874.51 -62.60 -36.75 9.12 1032.65
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) 4.139e+01 6.193e+01 0.668 0.507
## cases_1m 1.520e-02 2.342e-03 6.490 4.87e-08 ***
## tests_1m -2.209e-04 3.269e-04 -0.676 0.502
## population 3.709e-07 1.089e-06 0.341 0.735
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 281.2 on 47 degrees of freedom
## Multiple R-squared: 0.7049, Adjusted R-squared: 0.686
## F-statistic: 37.41 on 3 and 47 DF, p-value: 1.653e-12
car::vif(model_reduced)
## cases_1m tests_1m population
## 3.229886 3.330249 1.081183
Po odstránení silno korelovaných premenných (total_cases a total_tests) sa model stabilizoval. Hodnoty VIF klesli z extrémnych hodnôt (okolo 20) na prijateľné hodnoty pod 3.5. Reduced model si pritom zachoval veľmi dobrú vysvetľovaciu schopnosť (R² = 0.705). Jedinou štatisticky významnou premennou zostáva cases_1m, ktorá má jasný pozitívny vplyv na úmrtnosť. Premenné tests_1m a population nie sú významné, no nespôsobujú multikolinearitu a môžu v modeli slúžiť ako kontrolné premenné. Reduced model je preto vhodnejší na interpretáciu ako pôvodný model.
AIC(model_full, model_reduced)
## df AIC
## model_full 7 708.3808
## model_reduced 5 725.7646
anova(model_reduced, model_full)
## Analysis of Variance Table
##
## Model 1: deaths_1m ~ cases_1m + tests_1m + population
## Model 2: deaths_1m ~ cases_1m + tests_1m + total_cases + total_tests +
## population
## Res.Df RSS Df Sum of Sq F Pr(>F)
## 1 47 3717453
## 2 45 2444273 2 1273180 11.72 7.995e-05 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Podľa AIC je full model preferovaný (AIC = 708.38 oproti 725.76), pretože poskytuje o niečo lepšie prispôsobenie dátam napriek väčšiemu počtu parametrov. Napriek tomu však full model trpí extrémnou multikolinearitou (VIF približne 20), ktorá spôsobuje nestabilitu koeficientov a znižuje jeho interpretovateľnosť. Reduced model má síce mierne vyšší AIC, ale jeho koeficienty sú stabilné, multikolinearita je eliminovaná a model je vhodnejší pre interpretáciu.