packs <- c("tidyverse","janitor","broom","kableExtra","scales","GGally","stringr")
to_install <- packs[!packs %in% installed.packages()[, "Package"]]
if (length(to_install)) install.packages(to_install, dependencies = TRUE)
invisible(lapply(packs, library, character.only = TRUE))
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.1     ✔ stringr   1.5.2
## ✔ ggplot2   4.0.0     ✔ tibble    3.3.0
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.1.0     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## 
## Attaching package: 'janitor'
## 
## 
## The following objects are masked from 'package:stats':
## 
##     chisq.test, fisher.test
## 
## 
## 
## Attaching package: 'kableExtra'
## 
## 
## The following object is masked from 'package:dplyr':
## 
##     group_rows
## 
## 
## 
## Attaching package: 'scales'
## 
## 
## The following object is masked from 'package:purrr':
## 
##     discard
## 
## 
## The following object is masked from 'package:readr':
## 
##     col_factor
# Pomocná funkcia: prevod na numeric (odstráni čiarky a plusy)

to_num <- function(x) {
  if (is.numeric(x)) return(x)
  x <- as.character(x)
  # odstráň NBSP a zbytočné medzery
  x <- gsub("\u00A0", " ", x, fixed = TRUE)
  x <- trimws(x)
  # odstráň oddeľovače tisícov a plusy
  x <- gsub(",", "", x, fixed = TRUE)
  x <- gsub("+", "", x, fixed = TRUE)   # alternatíva k gsub("\\+", "", x)
  # prázdne/NA texty na NA
  x[x %in% c("", "NA", "N/A", "nan")] <- NA
  suppressWarnings(as.numeric(x))
}

if (!requireNamespace("hms", quietly = TRUE)) {
  options(repos = c(CRAN = "https://cloud.r-project.org"))
  install.packages("hms", dependencies = TRUE)
}

udaje <- readr::read_csv("covid_africa.csv", show_col_types = FALSE, progress = FALSE)

# úprava názvov (NBSP, viacnásobné medzery) + späť na pôvodný štýl s medzerami

names(udaje) <- names(udaje) |>
stringr::str_replace_all("\u00A0", " ") |>
stringr::str_squish()

udaje <- udaje %>% janitor::clean_names() %>%
dplyr::rename(
`Country/Other`      = country_other,
`Total Cases`        = total_cases,
`Total Deaths`       = total_deaths,
`Total Recovered`    = total_recovered,
`Active Cases`       = active_cases,
`Tot Cases/ 1M pop`  = tot_cases_1m_pop,
`Deaths/ 1M pop`     = deaths_1m_pop,
`Total Tests`        = total_tests,
`Tests/ 1M pop`      = tests_1m_pop,
`Population`         = population
)

# numerické stĺpce

num_cols <- intersect(c('Total Cases','Total Deaths','Total Recovered','Active Cases',
'Tot Cases/ 1M pop','Deaths/ 1M pop','Total Tests','Tests/ 1M pop','Population'),
names(udaje))
for (c in num_cols) udaje[[c]] <- to_num(udaje[[c]])

# vyhodenie agregátov 'Total'

if ("Country/Other" %in% names(udaje)) {
udaje <- udaje %>% dplyr::filter(!stringr::str_detect(`Country/Other`, regex("total", ignore_case = TRUE)))
}

head(udaje)
colnames(udaje)
##  [1] "Country/Other"     "Total Cases"       "Total Deaths"     
##  [4] "Total Recovered"   "Active Cases"      "Tot Cases/ 1M pop"
##  [7] "Deaths/ 1M pop"    "Total Tests"       "Tests/ 1M pop"    
## [10] "Population"
# Helper pre SI skrátenie (kompat. naprieč verziami scales)
lab_si <- if (utils::packageVersion("scales") >= "1.2.0") {
  # nový spôsob: label_number(scale_cut = cut_si(""))
  scales::label_number(scale_cut = scales::cut_si(""))
} else {
  # staršie verzie mali priamo label_number_si()
  scales::label_number_si()
}
options(repos = c(CRAN = "https://cloud.r-project.org"))
install.packages("dplyr")   # alebo celý tidyverse
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.5'
## (as 'lib' is unspecified)
udaje %>%
  ggplot(aes(x = `Total Cases`, y = `Total Deaths`)) +
  geom_point(alpha = 0.8) +
  scale_x_continuous(labels = lab_si) +   # <-- tu
  scale_y_continuous(labels = lab_si) +   # <-- a tu
  labs(title = "Total Cases vs. Total Deaths", x = "Total Cases", y = "Total Deaths") +
  theme_minimal(base_size = 13)

Na osi X je počet prípadov (Total Cases) a na osi Y je počet úmrtí (Total Deaths). Body ukazujú, že medzi počtom prípadov a úmrtí je pozitívny vzťah – pri viac prípadoch býva aj viac úmrtí. Väčšina krajín je sústredená pri nízkych hodnotách oboch veličín. Zároveň je viditeľný jeden výrazný odľahlý bod s približne 4 miliónmi prípadov a vyše 100 tisíc úmrtiami.

if ("Deaths/ 1M pop" %in% names(udaje)) {
d15 <- udaje %>%
dplyr::filter(!is.na(`Deaths/ 1M pop`)) %>%
dplyr::arrange(desc(`Deaths/ 1M pop`)) %>%
dplyr::slice_head(n = 15)

ggplot2::ggplot(d15, ggplot2::aes(x = reorder(`Country/Other`, `Deaths/ 1M pop`),
y = `Deaths/ 1M pop`)) +
ggplot2::geom_segment(ggplot2::aes(xend = `Country/Other`, y = 0, yend = `Deaths/ 1M pop`)) +
ggplot2::geom_point(size = 2) +
ggplot2::coord_flip() +
ggplot2::labs(title = "Top 15 – Deaths per 1M (lollipop)",
x = NULL, y = "Deaths per 1M") +
ggplot2::theme_minimal(base_size = 13)
}

Graf zobrazuje rebríček 15 krajín s najvyšším počtom úmrtí na milión obyvateľov. Každý „lízatkový“ riadok ukazuje hodnotu krajiny (bod) a jej vzdialenosť od nuly (čiara). Najvyššie je Tunisko (~2 500 úmrtí/1M), nasledované Seychelami a Južnou Afrikou (~1 800–1 700/1M). Ostatné krajiny sú nižšie, väčšina medzi ~500 až 1 500 úmrtí/1M, čo ukazuje výrazné rozdiely v per-capita záťaži.

req <- c("Tot Cases/ 1M pop","Deaths/ 1M pop")
if (all(req %in% names(udaje))) {
ggplot2::ggplot(udaje, ggplot2::aes(x = `Tot Cases/ 1M pop`, y = `Deaths/ 1M pop`)) +
ggplot2::geom_point(alpha = 0.8) +
ggplot2::geom_smooth(method = "lm", se = TRUE) +
ggplot2::labs(title = "Cases per 1M vs Deaths per 1M",
x = "Cases per 1M", y = "Deaths per 1M") +
ggplot2::theme_minimal(base_size = 13)
} else {
cat("Chýbajú stĺpce: ", paste(setdiff(req, names(udaje)), collapse = ", "), "\n")
}
## `geom_smooth()` using formula = 'y ~ x'

Na osi X sú prípady na milión (Cases per 1M) a na osi Y úmrtia na milión (Deaths per 1M). Modrá priamka je lineárny trend: viac prípadov na milión je spojených s vyššími úmrtiami na milión. Sivý pás predstavuje interval neistoty odhadu trendu. Väčšina bodov je pri nižších hodnotách prípadov, no sú aj krajiny s vyššími hodnotami, ktoré ležia nad či pod trendom (potenciálne odľahlé pozorovania).

req <- "Tot Cases/ 1M pop"
if (req %in% names(udaje)) {
ggplot2::ggplot(udaje, ggplot2::aes(y = `Tot Cases/ 1M pop`)) +
ggplot2::geom_boxplot(outlier.alpha = 0.5) +
ggplot2::scale_y_continuous(labels = lab_si) +
ggplot2::labs(title = "Boxplot: Cases per 1M",
x = NULL, y = "Cases per 1M") +
ggplot2::theme_minimal(base_size = 13)
} else {
cat("Chýba stĺpec 'Tot Cases/ 1M pop'.\n")
}

Boxplot zobrazuje rozdelenie hodnôt Cases per 1M naprieč krajinami. Krabica reprezentuje stredných 50 % hodnôt (IQR) a horizontálna čiarka vnútri je medián, ktorý je veľmi nízko. Vidno viacero odľahlých bodov výrazne nad bežným rozsahom, čo naznačuje, že pár krajín má podstatne vyššiu incidenciu prípadov na milión než väčšina ostatných.

req <- "Tests/ 1M pop"
if (req %in% names(udaje)) {
udaje %>%
dplyr::filter(!is.na(`Tests/ 1M pop`)) %>%
dplyr::arrange(desc(`Tests/ 1M pop`)) %>%
dplyr::slice_head(n = 10) %>%
ggplot2::ggplot(ggplot2::aes(x = reorder(`Country/Other`, `Tests/ 1M pop`),
y = `Tests/ 1M pop`)) +
ggplot2::geom_col() +
ggplot2::coord_flip() +
ggplot2::scale_y_continuous(labels = lab_si) +
ggplot2::labs(title = "Top 10 krajín podľa Tests per 1M",
x = NULL, y = "Tests per 1M") +
ggplot2::theme_minimal(base_size = 13)
} else {
cat("Chýba stĺpec 'Tests/ 1M pop'.\n")
}

Graf zobrazuje rebríček desiatich krajín s najvyšším počtom testov na milión obyvateľov. Najvyššie je Eswatini, nasledované Botswanou; obe výrazne prevyšujú ostatné krajiny. Hodnoty sú v stovkách tisíc testov na milión, čo naznačuje veľké rozdiely v intenzite testovania medzi krajinami.

# vyber kľúčové numerické stĺpce

sel <- c("Total Cases","Total Deaths","Total Recovered","Active Cases",
"Tot Cases/ 1M pop","Deaths/ 1M pop","Total Tests","Tests/ 1M pop","Population")
sel <- intersect(sel, names(udaje))

desc_tbl <- udaje %>%
dplyr::select(dplyr::all_of(sel)) %>%
tidyr::pivot_longer(everything(), names_to = "Premenná", values_to = "Hodnota") %>%
dplyr::group_by(Premenná) %>%
dplyr::summarise(
n      = sum(!is.na(Hodnota)),
mean   = mean(Hodnota, na.rm = TRUE),
sd     = stats::sd(Hodnota, na.rm = TRUE),
p25    = stats::quantile(Hodnota, 0.25, na.rm = TRUE),
median = stats::median(Hodnota, na.rm = TRUE),
p75    = stats::quantile(Hodnota, 0.75, na.rm = TRUE),
min    = min(Hodnota, na.rm = TRUE),
max    = max(Hodnota, na.rm = TRUE),
.groups = "drop"
)

# formátovanie čísel (SI skrátenie pre veľké hodnoty)

fmt_si <- function(x) scales::number(x, accuracy = 0.1, scale_cut = scales::cut_si(""))

desc_tbl %>%
dplyr::mutate(
mean   = fmt_si(mean),
sd     = fmt_si(sd),
p25    = fmt_si(p25),
median = fmt_si(median),
p75    = fmt_si(p75),
min    = fmt_si(min),
max    = fmt_si(max)
) %>%
kableExtra::kable(
caption = "Deskriptívne štatistiky vybraných metrík",
col.names = c("Premenná","n","Mean","SD","P25","Median","P75","Min","Max"),
align = "lrrrrrrrr"
) %>%
kableExtra::kable_styling(full_width = FALSE, bootstrap_options = c("striped","hover","condensed")) %>%
kableExtra::row_spec(0, bold = TRUE, background = "#f2f2f2")
Deskriptívne štatistiky vybraných metrík
Premenná n Mean SD P25 Median P75 Min Max
Active Cases 51 6.4 k 17.8 k 27.0 309.0 1.8 k 0.0 81.9 k
Deaths/ 1M pop 54 312.4 527.2 33.2 93.5 226.2 3.0 2.4 k
Population 54 26.0 M 37.6 M 2.9 M 13.7 M 31.6 M 99.4 k 216.7 M
Tests/ 1M pop 51 167.4 k 222.0 k 29.2 k 61.0 k 227.8 k 5.1 k 885.1 k
Tot Cases/ 1M pop 54 27.0 k 73.6 k 2.5 k 4.8 k 17.0 k 381.0 512.3 k
Total Cases 54 227.9 k 588.8 k 22.9 k 63.9 k 172.0 k 6.6 k 4.1 M
Total Deaths 54 4.8 k 14.7 k 291.2 1.0 k 3.1 k 38.0 102.6 k
Total Recovered 51 206.9 k 567.9 k 19.9 k 62.5 k 168.7 k 4.9 k 3.9 M
Total Tests 51 2.1 M 4.2 M 346.8 k 804.9 k 2.3 M 23.7 k 26.8 M
# výpočet CFR (%) a príprava rebríčka

rank_tbl <- udaje %>%
dplyr::mutate(`CFR (%)` = 100 * (`Total Deaths`/`Total Cases`)) %>%
dplyr::arrange(dplyr::desc(`Total Cases`)) %>%
dplyr::slice_head(n = 15) %>%
dplyr::select(
`Country/Other`,
`Total Cases`, `Total Deaths`, `Total Recovered`, `Active Cases`,
`Tot Cases/ 1M pop`, `Deaths/ 1M pop`, `Total Tests`, `Tests/ 1M pop`,
Population, `CFR (%)`
)

# formátovacie pomocníky

fmt_si <- function(x) scales::number(x, accuracy = 1, scale_cut = scales::cut_si(""))
fmt_pct1 <- function(x) ifelse(is.finite(x), paste0(scales::number(x, accuracy = 0.1), "%"), NA)

rank_tbl_fmt <- rank_tbl %>%
dplyr::mutate(
`Total Cases`       = fmt_si(`Total Cases`),
`Total Deaths`      = fmt_si(`Total Deaths`),
`Total Recovered`   = fmt_si(`Total Recovered`),
`Active Cases`      = fmt_si(`Active Cases`),
`Tot Cases/ 1M pop` = scales::number(`Tot Cases/ 1M pop`, accuracy = 1),
`Deaths/ 1M pop`    = scales::number(`Deaths/ 1M pop`, accuracy = 1),
`Total Tests`       = fmt_si(`Total Tests`),
`Tests/ 1M pop`     = scales::number(`Tests/ 1M pop`, accuracy = 1),
Population          = fmt_si(Population),
`CFR (%)`           = fmt_pct1(`CFR (%)`)
)

rank_tbl_fmt %>%
kableExtra::kable(
caption = "Top 15 krajín podľa Total Cases (s CFR a testovaním)",
align = "lrrrrrrrrrr"
) %>%
kableExtra::kable_styling(full_width = FALSE, bootstrap_options = c("striped","hover","condensed")) %>%
kableExtra::row_spec(0, bold = TRUE, background = "#f7f7f7") %>%
kableExtra::column_spec(1, bold = TRUE)
Top 15 krajín podľa Total Cases (s CFR a testovaním)
Country/Other Total Cases Total Deaths Total Recovered Active Cases Tot Cases/ 1M pop Deaths/ 1M pop Total Tests Tests/ 1M pop Population CFR (%)
South Africa 4 M 103 k 4 M 61 k 67 095 1 689 27 M 441 027 61 M 2.5%
Morocco 1 M 16 k 1 M 4 k 33 786 431 13 M 344 191 38 M 1.3%
Tunisia 1 M 29 k NA NA 95 741 2 442 5 M 416 164 12 M 2.6%
Egypt 516 k 25 k 442 k 49 k 4 861 232 4 M 34 792 106 M 4.8%
Libya 507 k 6 k 501 k 0 72 048 914 2 M 352 782 7 M 1.3%
Ethiopia 501 k 8 k 488 k 5 k 4 147 63 6 M 46 066 121 M 1.5%
Zambia 349 k 4 k 341 k 4 k 17 940 209 4 M 211 244 19 M 1.2%
Kenya 344 k 6 k 337 k 957 6 119 101 4 M 70 569 56 M 1.7%
Botswana 330 k 3 k 327 k 406 135 286 1 147 2 M 830 300 2 M 0.8%
Algeria 272 k 7 k 183 k 82 k 5 995 152 231 k 5 093 45 M 2.5%
Nigeria 267 k 3 k 260 k 4 k 1 230 15 6 M 26 339 217 M 1.2%
Zimbabwe 266 k 6 k 259 k 1 k 17 333 373 3 M 164 744 15 M 2.2%
Mozambique 233 k 2 k 229 k 2 k 7 054 68 1 M 41 437 33 M 1.0%
Namibia 172 k 4 k 167 k 801 65 302 1 556 1 M 403 460 3 M 2.4%
Uganda 172 k 4 k 100 k 68 k 3 548 75 3 M 62 198 48 M 2.1%
# Knižnice používané v pôvodnom cvičení
library(zoo)
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(tseries)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
library(lmtest)
library(sandwich)
library(car)
## Loading required package: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
## The following object is masked from 'package:purrr':
## 
##     some
rm(list = ls())
options(scipen = 999)
data <- read.csv("covid_africa.csv")
names(data) <- make.names(names(data)) # nahradí medzery bodkami
head(data)
library(dplyr)
library(tidyr)
library(ggplot2)
library(car)
library(tseries)


# Vyberieme relevantné premenné
covid <- data %>%
select(Country.Other, Total.Cases, Total.Deaths, Population, Tests..1M.pop)


# Zistenie počtu NA
colSums(is.na(covid))
## Country.Other   Total.Cases  Total.Deaths    Population Tests..1M.pop 
##             0             0             0             0             3
# Imputácia chýbajúci hodnôt mediánom
covid <- covid %>% mutate(across(where(is.numeric), ~ifelse(is.na(.), median(., na.rm = TRUE), .)))
par(mfrow = c(2,2))
boxplot(covid$Total.Cases, main="Total Cases")
boxplot(covid$Total.Deaths, main="Total Deaths")
boxplot(covid$Population, main="Population")
boxplot(covid$Tests..1M.pop, main="Tests per 1M pop")

Interpretácia boxplotov

  1. Total Cases (Celkový počet prípadov)

Väčšina krajín má veľmi nízky počet prípadov (dolná časť grafu je silne stlačená).

Niekoľko krajín má extrémne vysoké hodnoty — výrazné odľahlé hodnoty (body nad „fúzmi“).

To znamená, že distribúcia je silne pravostranná (asymetrická) – pár krajín (napr. Južná Afrika, Egypt) má oveľa viac prípadov než ostatné.

  1. Total Deaths (Celkový počet úmrtí)

Rovnaký vzorec ako pri „Total Cases“ – väčšina krajín má málo úmrtí, niekoľko má extrémne veľa.

Opäť ide o prítomnosť odľahlých hodnôt – krajiny s vyšším počtom úmrtí ťahajú priemer nahor.

Variabilita je relatívne malá v porovnaní s extrémami.

  1. Population (Populácia)

Rozptyl je oveľa väčší — ale aj tu vidíme niekoľko veľkých populácií (napr. Nigéria, Etiópia).

Väčšina krajín má populáciu do niekoľkých desiatok miliónov, zatiaľ čo niektoré krajiny výrazne vyčnievajú.

Opäť ide o pravostranné rozdelenie.

  1. Tests per 1M pop (Počet testov na milión obyvateľov)

Distribúcia je menej extrémna, ale stále obsahuje odľahlé hodnoty – krajiny, ktoré testovali výrazne viac (napr. Juhoafrická republika).

Väčšina krajín testovala v pomerne nízkej miere, čo svedčí o nerovnomernom prístupe k testovaniu.

model <- lm(Total.Deaths ~ Total.Cases + Population + Tests..1M.pop, data = covid)
summary(model)
## 
## Call:
## lm(formula = Total.Deaths ~ Total.Cases + Population + Tests..1M.pop, 
##     data = covid)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -13696.3   -258.7    213.0    696.0  12661.4 
## 
## Coefficients:
##                     Estimate     Std. Error t value            Pr(>|t|)    
## (Intercept)   -174.374664320  663.543202530  -0.263               0.794    
## Total.Cases      0.024720197    0.000796924  31.020 <0.0000000000000002 ***
## Population      -0.000004795    0.000012492  -0.384               0.703    
## Tests..1M.pop   -0.003482110    0.002181018  -1.597               0.117    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 3123 on 50 degrees of freedom
## Multiple R-squared:  0.9571, Adjusted R-squared:  0.9546 
## F-statistic: 372.1 on 3 and 50 DF,  p-value: < 0.00000000000000022
par(mfrow = c(2,2))
plot(model)

# Testy normality a odľahlých hodnôt
jarque.bera.test(model$residuals)
## 
##  Jarque Bera Test
## 
## data:  model$residuals
## X-squared = 283.45, df = 2, p-value < 0.00000000000000022
outlierTest(model)
##     rstudent unadjusted p-value Bonferroni p
## 35 -5.939502      0.00000029003  0.000015661
## 15  5.329668      0.00000247500  0.000133650

🟦 1. Residuals vs Fitted

Interpretácia: Body sú trochu roztrúsené, ale nie úplne náhodne — mierne zakrivenie naznačuje, že vzťah nemusí byť dokonale lineárny. → Model by sa mohol zlepšiť pridaním nelineárneho člena alebo transformáciou premenných.

🟩 2. Q-Q Residuals

Interpretácia: Väčšina bodov leží na čiare, ale niektoré odchýlky na koncoch (napr. 46, 35) znamenajú, že rozdelenie reziduí nie je úplne normálne. → Môžu existovať extrémne hodnoty (outliery).

🟧 3. Scale-Location

Interpretácia: Červená čiara je relatívne rovná, no body na konci trochu stúpajú — to znamená mierne nerovnomerný rozptyl (možná heteroskedasticita). → Vhodné by bolo zvážiť transformáciu závislej premennej.

🟥 4. Residuals vs Leverage

Interpretácia: Väčšina bodov má nízku páku (leverage), ale napr. bod 46 má vyšší vplyv. → Tento bod môže neprimerane ovplyvňovať výsledky modelu.

# Q-Q plot pre reziduá pôvodného modelu
qqnorm(model$residuals,
       main = "Q-Q Plot – Reziduá pôvodného modelu",
       pch = 19, col = "darkblue")
qqline(model$residuals, col = "red", lwd = 2)

model_log <- lm(log(Total.Deaths + 1) ~ log(Total.Cases + 1) + log(Population + 1) + log(Tests..1M.pop + 1), data = covid)
summary(model_log)
## 
## Call:
## lm(formula = log(Total.Deaths + 1) ~ log(Total.Cases + 1) + log(Population + 
##     1) + log(Tests..1M.pop + 1), data = covid)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -3.06222 -0.29338  0.01604  0.45642  1.45352 
## 
## Coefficients:
##                        Estimate Std. Error t value        Pr(>|t|)    
## (Intercept)            -6.43830    1.95654  -3.291         0.00184 ** 
## log(Total.Cases + 1)    0.91868    0.11026   8.332 0.0000000000512 ***
## log(Population + 1)     0.17183    0.10352   1.660         0.10320    
## log(Tests..1M.pop + 1)  0.03325    0.11808   0.282         0.77939    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.7064 on 50 degrees of freedom
## Multiple R-squared:  0.832,  Adjusted R-squared:  0.8219 
## F-statistic: 82.53 on 3 and 50 DF,  p-value: < 0.00000000000000022
par(mfrow = c(2,2))
plot(model_log)

jarque.bera.test(model_log$residuals)
## 
##  Jarque Bera Test
## 
## data:  model_log$residuals
## X-squared = 91.194, df = 2, p-value < 0.00000000000000022
outlierTest(model_log)
##    rstudent unadjusted p-value Bonferroni p
## 6 -5.577742       0.0000010394  0.000056129