knitr::opts_chunk$set(
echo = TRUE,
message = FALSE,
warning = FALSE
)Práca s databázou: Verejné financie a štátny rozpočet
Spracované a inšpirované podkladmi k predmetu Ekonometria a verejne dostupnými dátami Eurostatu.
Práca s údajmi
Tradičná práca s databázou
Pre prácu s údajmi (databázou) používame najčastejšie dátový typ data.frame. Je to tabuľka, ktorá pozostáva zo stĺpcov rozličných typov. Jeden riadok pritom predstavuje jeden záznam databázy (napr. jednu rozpočtovú kapitolu alebo jeden rok).
Príklad: Rozpočtové kapitoly SR
Majme údaje o vybraných rozpočtových kapitolách SR, ktoré predstavujú tri premenné – Kapitola, Vydavky_mld (v mld. EUR) a Priorita_body (interné hodnotenie priority 0–100):
# Vytvorenie izolovaných vektorov pre rozpočtové kapitoly
Kapitola = c("Zdravotníctvo", "Školstvo", "Obrana")
Vydavky_mld = c(7.8, 4.5, 2.7)
Priorita_body = c(95, 90, 78)Tieto tri premenné spojíme do jednej tabuľky (data.frame) nasledovne:
udaje <- data.frame(Kapitola, Vydavky_mld, Priorita_body)
print(udaje) Kapitola Vydavky_mld Priorita_body
1 Zdravotníctvo 7.8 95
2 Školstvo 4.5 90
3 Obrana 2.7 78
Niektoré základné operácie s údajmi organizovanými v data.frame sú uvedené nižšie:
print(udaje$Vydavky_mld) # adresovanie konkrétneho stĺpca (výdavky)[1] 7.8 4.5 2.7
print(mean(udaje$Vydavky_mld)) # priemerné výdavky na kapitolu[1] 5
print(udaje[Kapitola == "Školstvo", ]) # adresovanie celého riadku pre Školstvo Kapitola Vydavky_mld Priorita_body
2 Školstvo 4.5 90
print(udaje[3, ]) # výpis tretieho riadku (Obrana) Kapitola Vydavky_mld Priorita_body
3 Obrana 2.7 78
print(udaje[, 2:3]) # vypísanie druhého a tretieho stĺpca tabuľky Vydavky_mld Priorita_body
1 7.8 95
2 4.5 90
3 2.7 78
print(udaje[1, 1]) # vypísanie prvej bunky tabuľky[1] "Zdravotníctvo"
summary(udaje) # základná deskriptívna štatistika celej tabuľky Kapitola Vydavky_mld Priorita_body
Length : 3 Min. :2.70 Min. :78.00
N.unique : 3 1st Qu.:3.60 1st Qu.:84.00
N.blank : 0 Median :4.50 Median :90.00
Min.nchar: 6 Mean :5.00 Mean :87.67
Max.nchar:13 3rd Qu.:6.15 3rd Qu.:92.50
Max. :7.80 Max. :95.00
Ak chceme pridať k tabuľke dodatočný stĺpec (napr. či kapitola dodržala rozpočtový strop DodrzanyLimit), urobíme to pomocou cbind:
DodrzanyLimit <- c(FALSE, TRUE, TRUE)
udaje <- cbind(udaje, DodrzanyLimit)
print(udaje) Kapitola Vydavky_mld Priorita_body DodrzanyLimit
1 Zdravotníctvo 7.8 95 FALSE
2 Školstvo 4.5 90 TRUE
3 Obrana 2.7 78 TRUE
Ak chceme pridať nový riadok (ďalšiu rozpočtovú kapitolu, napr. Doprava), použijeme rbind:
# Nový záznam (musí sedieť štruktúra a názvy stĺpcov)
novy.riadok <- data.frame(
Kapitola = "Doprava",
Vydavky_mld = 3.45,
Priorita_body = 65,
DodrzanyLimit = FALSE
)
# Pripojenie riadku
udaje <- rbind(udaje, novy.riadok)
print(udaje) Kapitola Vydavky_mld Priorita_body DodrzanyLimit
1 Zdravotníctvo 7.80 95 FALSE
2 Školstvo 4.50 90 TRUE
3 Obrana 2.70 78 TRUE
4 Doprava 3.45 65 FALSE
Tabuľky v prostredí kableExtra
library(knitr)
library(kableExtra)
kable(
udaje,
digits = 2,
align = c("l", "c", "c", "r"),
caption = "Prehľad vybraných kapitol štátneho rozpočtu SR"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = FALSE,
position = "center"
)| Kapitola | Vydavky_mld | Priorita_body | DodrzanyLimit |
|---|---|---|---|
| Zdravotníctvo | 7.80 | 95 | FALSE |
| Školstvo | 4.50 | 90 | TRUE |
| Obrana | 2.70 | 78 | TRUE |
| Doprava | 3.45 | 65 | FALSE |
Tidyverse – moderná práca s údajmi
Tidyverse je súbor moderných knižníc, ktoré zjednodušujú manipuláciu a vizualizáciu dát.
library(tidyverse)dplyr – pre manipuláciu s údajmi
Knižnica dplyr poskytuje kľúčové funkcie: filter(), select(), mutate(), arrange() a summarise(), ktoré spájame pomocou operátora pipe %>%.
Výber a triedenie
# Výber kapitol s prioritou nad 70 bodov a zoradenie od najväčších výdavkov
udaje %>%
filter(Priorita_body > 70) %>%
arrange(desc(Vydavky_mld)) %>%
kable(caption = "Kľúčové rozpočtové kapitoly zoradené podľa výdavkov") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = FALSE,
position = "center"
)| Kapitola | Vydavky_mld | Priorita_body | DodrzanyLimit |
|---|---|---|---|
| Zdravotníctvo | 7.8 | 95 | FALSE |
| Školstvo | 4.5 | 90 | TRUE |
| Obrana | 2.7 | 78 | TRUE |
Zoskupenie a sumarizácia
# Zoskupenie podľa dodržania limitu a výpočet priemerných výdavkov
udaje %>%
group_by(DodrzanyLimit) %>%
summarise(
Priem.Vydavky = mean(Vydavky_mld),
Pocet = n()
) %>%
kable(
digits = 2,
caption = "Priemerné výdavky (v mld. EUR) podľa dodržania rozpočtového limitu",
col.names = c("Dodržaný Limit", "Priemerné Výdavky", "Počet kapitol"),
align = "c"
) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = FALSE,
position = "center"
)| Dodržaný Limit | Priemerné Výdavky | Počet kapitol |
|---|---|---|
| FALSE | 5.62 | 2 |
| TRUE | 3.60 | 2 |
Vytváranie novej premennej
# Hodnotenie priority písmenom a výpočet odchýlky výdavkov od 3 mld. EUR
udaje %>%
mutate(
Kategoria = case_when(
Priorita_body >= 90 ~ "A (Kritická)",
Priorita_body >= 80 ~ "B (Vysoká)",
Priorita_body >= 70 ~ "C (Stredná)",
TRUE ~ "D (Bežná)"
),
Nad_3mld = round(Vydavky_mld - 3, 2)
) %>%
kable(caption = "Kategorizácia rozpočtových kapitol") %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = FALSE,
position = "center"
) | Kapitola | Vydavky_mld | Priorita_body | DodrzanyLimit | Kategoria | Nad_3mld |
|---|---|---|---|---|---|
| Zdravotníctvo | 7.80 | 95 | FALSE | A (Kritická) | 4.80 |
| Školstvo | 4.50 | 90 | TRUE | A (Kritická) | 1.50 |
| Obrana | 2.70 | 78 | TRUE | C (Stredná) | -0.30 |
| Doprava | 3.45 | 65 | FALSE | D (Bežná) | 0.45 |
Import údajov z otvorených databáz
V prostredí R máme prístup k vstavaným databázam v knižniciach datasets alebo ekonometrickej knižnici wooldridge:
library(datasets)
ds <- as.data.frame(utils::data(package = "datasets")$results)[, c("Item","Title")]
knitr::kable(head(ds, 10), col.names = c("Dataset", "Title"))| Dataset | Title |
|---|---|
| AirPassengers | Monthly Airline Passenger Numbers 1949-1960 |
| BJsales | Sales Data with Leading Indicator |
| BJsales.lead (BJsales) | Sales Data with Leading Indicator |
| BOD | Biochemical Oxygen Demand |
| CO2 | Carbon Dioxide Uptake in Grass Plants |
| ChickWeight | Weight Versus Age of Chicks on Different Diets |
| DNase | Elisa assay of DNase |
| EuStockMarkets | Daily Closing Prices of Major European Stock Indices, 1991-1998 |
| Formaldehyde | Determination of Formaldehyde |
| HairEyeColor | Hair and Eye Color of Statistics Students |
Ukážka databáz z balíka wooldridge:
library(wooldridge)
ds_w <- as.data.frame(utils::data(package = "wooldridge")$results)[, c("Item","Title")]
knitr::kable(head(ds_w, 10), col.names = c("Dataset", "Title")) %>%
kable_styling(
bootstrap_options = c("striped", "hover", "condensed", "responsive"),
full_width = FALSE,
position = "center"
)| Dataset | Title |
|---|---|
| admnrev | admnrev |
| affairs | affairs |
| airfare | airfare |
| alcohol | alcohol |
| apple | apple |
| approval | approval |
| athlet1 | athlet1 |
| athlet2 | athlet2 |
| attend | attend |
| audit | audit |
Import vlastných údajov o štátnom rozpočte (.csv)
Pre analýzu sme zostavili panelovú databázu verejných financií a makroekonomických ukazovateľov krajín V4 (Slovensko, Česko, Poľsko, Maďarsko) v časovom rade za roky 2013 až 2023 na základe údajov Eurostatu (Rozpocet_V4.csv). Ako oddeľovač stĺpcov je použitá bodkočiarka ; a ako desatinný oddeľovač bodka ..
Import údajov do data.frame zrealizujeme nasledovne:
udaje_v4 <- read.csv2("udaje/Rozpocet_V4.csv", header = TRUE, sep = ";", dec = ".")
head(udaje_v4) # prvých niekoľko riadkov YEARS COUNTRY REVENUE_GDP EXPENDITURE_GDP DEFICIT_SURPLUS DEBT_TO_GDP
1 2013 Slovakia 38.7 41.6 -2.9 54.7
2 2014 Slovakia 39.3 42.4 -3.1 53.5
3 2015 Slovakia 42.5 45.1 -2.6 51.7
4 2016 Slovakia 40.0 42.3 -2.3 52.3
5 2017 Slovakia 38.5 39.5 -1.0 51.5
6 2018 Slovakia 38.7 39.7 -1.0 49.4
GDP_GROWTH INFLATION
1 0.7 1.5
2 2.7 -0.1
3 5.2 -0.3
4 1.9 -0.5
5 2.9 1.4
6 4.0 2.5
colnames(udaje_v4) # názvy premenných[1] "YEARS" "COUNTRY" "REVENUE_GDP" "EXPENDITURE_GDP"
[5] "DEFICIT_SURPLUS" "DEBT_TO_GDP" "GDP_GROWTH" "INFLATION"
Grafy
ggplot2 – knižnica pre grafy
Vyberieme si podmnožinu údajov (napr. pre Slovensko alebo pre konkrétne premenné):
library(dplyr)
udaje.sk <- udaje_v4 %>%
filter(COUNTRY == "Slovakia") %>%
dplyr::select(YEARS, REVENUE_GDP, EXPENDITURE_GDP, DEFICIT_SURPLUS, DEBT_TO_GDP, GDP_GROWTH)Scatter plot (Bodový graf)
Zobrazíme vzťah medzi reálnym rastom HDP (GDP_GROWTH) a saldom štátneho rozpočtu (DEFICIT_SURPLUS) vo všetkých krajinách V4:
library(ggplot2)
ggplot(udaje_v4, aes(x = GDP_GROWTH, y = DEFICIT_SURPLUS, color = COUNTRY)) +
geom_point(size = 3) +
theme_minimal() +
labs(
title = "Vzťah medzi rastom HDP a saldom rozpočtu v krajinách V4 (2013–2023)",
x = "Rast HDP (%)",
y = "Saldo rozpočtu (% HDP)",
color = "Krajina"
)Boxplot (Krabicový graf)
Porovnanie rozdelenia verejného dlhu (DEBT_TO_GDP) alebo salda rozpočtu v jednotlivých rokoch a krajinách:
ggplot(udaje_v4, aes(x = factor(YEARS), y = DEFICIT_SURPLUS)) +
geom_boxplot(fill = "lightblue", color = "darkblue") +
labs(
title = "Vývoj salda verejných financií v regióne V4 podľa rokov",
x = "Rok",
y = "Deficit / Prebytok (% HDP)"
) +
theme_minimal()Základné štatistiky
Súhrnná tabuľka cez knitr a kableExtra
Vypočítame základné deskriptívne štatistiky pre verejný dlh (% HDP) v krajinách V4 vo vybranom období 2018 – 2023:
library(dplyr)
library(knitr)
library(kableExtra)
dlh.stats <- udaje_v4 %>%
filter(YEARS %in% 2018:2023) %>%
group_by(YEARS) %>%
summarise(
n = n(),
mean = mean(DEBT_TO_GDP, na.rm = TRUE),
sd = sd(DEBT_TO_GDP, na.rm = TRUE),
min = min(DEBT_TO_GDP, na.rm = TRUE),
q25 = quantile(DEBT_TO_GDP, 0.25, na.rm = TRUE),
median = median(DEBT_TO_GDP, 0.50, na.rm = TRUE),
q75 = quantile(DEBT_TO_GDP, 0.75, na.rm = TRUE),
max = max(DEBT_TO_GDP, na.rm = TRUE),
.groups = "drop"
)
dlh.stats %>%
kable(digits = 2, caption = "Základné štatistiky verejného dlhu (% HDP) v krajinách V4 (2018–2023)") %>%
kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
row_spec(0, bold = TRUE, background = "#f2f2f2") %>%
add_header_above(c(" " = 2, "Štatistiky verejného dlhu (% HDP)" = 7))| YEARS | n | mean | sd | min | q25 | median | q75 | max |
|---|---|---|---|---|---|---|---|---|
| 2018 | 4 | 49.83 | 15.13 | 32.1 | 44.55 | 49.05 | 54.32 | 69.1 |
| 2019 | 4 | 47.25 | 14.45 | 30.0 | 41.78 | 46.85 | 52.33 | 65.3 |
| 2020 | 4 | 58.27 | 17.00 | 37.7 | 52.33 | 58.05 | 64.00 | 79.3 |
| 2021 | 4 | 58.35 | 14.54 | 42.0 | 50.70 | 57.35 | 65.00 | 76.7 |
| 2022 | 4 | 56.30 | 13.11 | 44.2 | 47.95 | 53.45 | 61.80 | 74.1 |
| 2023 | 4 | 55.77 | 12.79 | 44.0 | 48.20 | 52.80 | 60.38 | 73.5 |
t-test: Porovnanie priemerného salda rozpočtu pred pandémiou (2019) a počas pandémie (2020)
t.test.result <- t.test(
udaje_v4$DEFICIT_SURPLUS[udaje_v4$YEARS == 2019],
udaje_v4$DEFICIT_SURPLUS[udaje_v4$YEARS == 2020]
)
print(t.test.result)
Welch Two Sample t-test
data: udaje_v4$DEFICIT_SURPLUS[udaje_v4$YEARS == 2019] and udaje_v4$DEFICIT_SURPLUS[udaje_v4$YEARS == 2020]
t = 7.9283, df = 5.9874, p-value = 0.0002161
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
3.818954 7.231046
sample estimates:
mean of x mean of y
-0.900 -6.425
ANOVA: Porovnanie výšky verejného dlhu medzi krajinami V4
anova.result <- aov(DEBT_TO_GDP ~ COUNTRY, data = udaje_v4)
summary(anova.result) Df Sum Sq Mean Sq F value Pr(>F)
COUNTRY 3 7016 2338.7 134.4 <2e-16 ***
Residuals 40 696 17.4
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Lineárna regresia: Modelovanie salda štátneho rozpočtu
Skúmame, ako na saldo štátneho rozpočtu (DEFICIT_SURPLUS) vplýva tempo rastu HDP (GDP_GROWTH), úroveň verejného dlhu (DEBT_TO_GDP) a inflácia (INFLATION):
model <- lm(DEFICIT_SURPLUS ~ GDP_GROWTH + DEBT_TO_GDP + INFLATION, data = udaje_v4)
summary(model)
Call:
lm(formula = DEFICIT_SURPLUS ~ GDP_GROWTH + DEBT_TO_GDP + INFLATION,
data = udaje_v4)
Residuals:
Min 1Q Median 3Q Max
-3.8789 -0.8079 0.1562 0.9645 2.8656
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 1.06768 1.02228 1.044 0.302567
GDP_GROWTH 0.33284 0.08476 3.927 0.000331 ***
DEBT_TO_GDP -0.07821 0.01773 -4.411 7.56e-05 ***
INFLATION -0.14489 0.04981 -2.909 0.005895 **
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 1.547 on 40 degrees of freedom
Multiple R-squared: 0.5571, Adjusted R-squared: 0.5239
F-statistic: 16.77 on 3 and 40 DF, p-value: 3.292e-07
Prehľadné spracovanie výsledkov regresie pomocou knižnice broom a kableExtra:
library(broom)
library(dplyr)
library(kableExtra)
library(stringr)
coef.tbl <- tidy(model, conf.int = TRUE) %>%
mutate(
term = dplyr::recode(term,
"(Intercept)" = "Konštanta (Intercept)",
"GDP_GROWTH" = "Rast HDP (%)",
"DEBT_TO_GDP" = "Verejný dlh (% HDP)",
"INFLATION" = "Inflácia (%)"
),
stars = case_when(
p.value < 0.001 ~ "***",
p.value < 0.01 ~ "**",
p.value < 0.05 ~ "*",
p.value < 0.1 ~ "·",
TRUE ~ ""
)
) %>%
transmute(
Premenná = term,
Odhad = estimate,
`Štand. chyba` = std.error,
`t-hodnota` = statistic,
`p-hodnota` = p.value,
`95% IS` = str_c("[", round(conf.low, 3), ", ", round(conf.high, 3), "]"),
Signif. = stars
)
coef.tbl %>%
kable(
digits = 3,
caption = "Výsledky OLS regresie (Závislá premenná: DEFICIT_SURPLUS)"
) %>%
kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover", "condensed")) %>%
column_spec(1, bold = TRUE) %>%
row_spec(0, bold = TRUE, background = "#f2f2f2") %>%
footnote(
general = "Kódy významnosti: *** p<0.001, ** p<0.01, * p<0.05, · p<0.1.",
threeparttable = TRUE
)| Premenná | Odhad | Štand. chyba | t-hodnota | p-hodnota | 95% IS | Signif. |
|---|---|---|---|---|---|---|
| Konštanta (Intercept) | 1.068 | 1.022 | 1.044 | 0.303 | [-0.998, 3.134] | |
| Rast HDP (%) | 0.333 | 0.085 | 3.927 | 0.000 | [0.162, 0.504] | *** |
| Verejný dlh (% HDP) | -0.078 | 0.018 | -4.411 | 0.000 | [-0.114, -0.042] | *** |
| Inflácia (%) | -0.145 | 0.050 | -2.909 | 0.006 | [-0.246, -0.044] | ** |
| Note: | ||||||
| Kódy významnosti: *** p<0.001, ** p<0.01, * p<0.05, · p<0.1. |
Tabuľka kvality regresného modelu (glance):
fit.tbl <- glance(model) %>%
transmute(
`R-squared` = r.squared,
`Adj. R-squared` = adj.r.squared,
`F-statistic` = statistic,
`F p-value` = p.value,
`AIC` = AIC,
`BIC` = BIC,
`Počet poz.` = nobs
)
fit.tbl %>%
kable(digits = 3, caption = "Štatistiky kvality modelu (Model Fit Statistics)") %>%
kable_styling(full_width = FALSE, bootstrap_options = c("condensed"))| R-squared | Adj. R-squared | F-statistic | F p-value | AIC | BIC | Počet poz. |
|---|---|---|---|---|---|---|
| 0.557 | 0.524 | 16.774 | 0 | 169.067 | 177.988 | 44 |