Práca s databázou: Verejné financie a štátny rozpočet

Author

Martin Petko

Published

today

knitr::opts_chunk$set(
    echo = TRUE,
    message = FALSE,
    warning = FALSE
)

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"
  )
Prehľad vybraných kapitol štátneho rozpočtu SR
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"
  )
Kľúčové rozpočtové kapitoly zoradené podľa výdavkov
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"
  )
Priemerné výdavky (v mld. EUR) podľa dodržania rozpočtového limitu
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"
  ) 
Kategorizácia rozpočtových kapitol
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))
Základné štatistiky verejného dlhu (% HDP) v krajinách V4 (2018–2023)
Štatistiky verejného dlhu (% HDP)
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
  )
Výsledky OLS regresie (Závislá premenná: DEFICIT_SURPLUS)
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"))
Štatistiky kvality modelu (Model Fit Statistics)
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