Cieľom tohto cvičenia je vykonať zhlukovú analýzu na prierezových
údajoch.
Ako príklad používam mieru nezamestnanosti v roku 2024
pre tri európske krajiny:
Každý riadok v dátach predstavuje jednu krajinu a
premennou záujmu je miera nezamestnanosti v % z pracovnej sily.
Pôvodné dáta mali panelový charakter (viaceré roky), ale pre účely tejto
úlohy som si vybrala iba rok 2024, čím vznikli
prierezové údaje.
V tejto časti načítam CSV súbor z Eurostatu
(une_rt_a__custom_18708117_linear.csv) a vytvorím
prierezový dataset pre rok 2024.
rm(list = ls())
library(dplyr)
library(knitr)
library(kableExtra)
# upravím si cestu k súboru podľa seba
udaje <- read.csv("une_rt_a__custom_18708117_linear.csv",
stringsAsFactors = FALSE)
str(udaje)
## 'data.frame': 33 obs. of 11 variables:
## $ DATAFLOW : chr "ESTAT:UNE_RT_A(1.0)" "ESTAT:UNE_RT_A(1.0)" "ESTAT:UNE_RT_A(1.0)" "ESTAT:UNE_RT_A(1.0)" ...
## $ LAST.UPDATE: chr "11/09/25 23:00:00" "11/09/25 23:00:00" "11/09/25 23:00:00" "11/09/25 23:00:00" ...
## $ freq : chr "Annual" "Annual" "Annual" "Annual" ...
## $ age : chr "From 15 to 74 years" "From 15 to 74 years" "From 15 to 74 years" "From 15 to 74 years" ...
## $ unit : chr "Percentage of population in the labour force" "Percentage of population in the labour force" "Percentage of population in the labour force" "Percentage of population in the labour force" ...
## $ sex : chr "Total" "Total" "Total" "Total" ...
## $ geo : chr "Czechia" "Czechia" "Czechia" "Czechia" ...
## $ TIME_PERIOD: int 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 ...
## $ OBS_VALUE : num 6.1 5.1 4 2.9 2.2 2 2.6 2.8 2.2 2.6 ...
## $ OBS_FLAG : chr "" "" "" "" ...
## $ CONF_STATUS: logi NA NA NA NA NA NA ...
head(udaje)
## DATAFLOW LAST.UPDATE freq age
## 1 ESTAT:UNE_RT_A(1.0) 11/09/25 23:00:00 Annual From 15 to 74 years
## 2 ESTAT:UNE_RT_A(1.0) 11/09/25 23:00:00 Annual From 15 to 74 years
## 3 ESTAT:UNE_RT_A(1.0) 11/09/25 23:00:00 Annual From 15 to 74 years
## 4 ESTAT:UNE_RT_A(1.0) 11/09/25 23:00:00 Annual From 15 to 74 years
## 5 ESTAT:UNE_RT_A(1.0) 11/09/25 23:00:00 Annual From 15 to 74 years
## 6 ESTAT:UNE_RT_A(1.0) 11/09/25 23:00:00 Annual From 15 to 74 years
## unit sex geo TIME_PERIOD
## 1 Percentage of population in the labour force Total Czechia 2014
## 2 Percentage of population in the labour force Total Czechia 2015
## 3 Percentage of population in the labour force Total Czechia 2016
## 4 Percentage of population in the labour force Total Czechia 2017
## 5 Percentage of population in the labour force Total Czechia 2018
## 6 Percentage of population in the labour force Total Czechia 2019
## OBS_VALUE OBS_FLAG CONF_STATUS
## 1 6.1 NA
## 2 5.1 NA
## 3 4.0 NA
## 4 2.9 NA
## 5 2.2 NA
## 6 2.0 NA
Vyberiem iba rok 2024 a premenné, ktoré potrebujem:
udaje2024 <- udaje %>%
dplyr::filter(TIME_PERIOD == 2024) %>%
dplyr::select(
Country = geo,
Unemployment = OBS_VALUE
)
# nastavím názvy riadkov podľa krajín
rownames(udaje2024) <- udaje2024$Country
udaje2024$Country <- NULL
kable(udaje2024,
caption = "Prierezové údaje – miera nezamestnanosti v roku 2024 (v %)",
digits = 1) %>%
kable_styling(full_width = FALSE)
| Unemployment | |
|---|---|
| Czechia | 2.6 |
| Germany | 3.4 |
| Slovakia | 5.3 |
Komentár:
Dataset je prierezový, pretože:
V zhlukovej analýze sa často používa štandardizácia (z-skóre), aby premenné s rôznymi jednotkami či mierkami mali porovnateľný vplyv na vzdialenosti.
V mojom prípade mám iba jednu premennú Unemployment, ale
pre úplnosť ju tiež štandardizujem.
# odstránenie prípadných NA (pre istotu)
udaje_complete <- na.omit(udaje2024)
# škálovanie (z-skóre)
udaje_scaled <- scale(udaje_complete)
udaje_scaled <- as.data.frame(udaje_scaled)
kable(udaje_scaled,
caption = "Škálované hodnoty miery nezamestnanosti (z-skóre)",
digits = 3) %>%
kable_styling(full_width = FALSE)
| Unemployment | |
|---|---|
| Czechia | -0.841 |
| Germany | -0.264 |
| Slovakia | 1.106 |
Teraz si zobrazím boxplot škálovaných hodnôt.
boxplot(
udaje_scaled$Unemployment,
main = "Škálovaná miera nezamestnanosti (z-skóre)",
ylab = "Unemployment (z-skóre)"
)
Komentár:
Keďže mám len 3 krajiny, boxplot je skôr ilustračný. Napriek tomu
ukazuje, či niektorá krajina výraznejšie „vyčnieva“ (má vyššiu alebo
nižšiu nezamestnanosť v porovnaní s ostatnými).
Pri viacerých premenných by som skúmala korelačnú maticu.
Tu mám iba jednu premennú, takže korelácia je triviálne rovná 1.
cor_mat <- cor(udaje_scaled, use = "pairwise.complete.obs")
round(cor_mat, 2)
## Unemployment
## Unemployment 1
Dôležitejšia je pre mňa matica vzdialeností medzi
krajinami, ktorú použijem v zhlukovaní.
Použijem euklidovskú vzdialenosť.
dist_mat <- dist(udaje_scaled, method = "euclidean")
round(as.matrix(dist_mat), 3)
## Czechia Germany Slovakia
## Czechia 0.000 0.577 1.947
## Germany 0.577 0.000 1.370
## Slovakia 1.947 1.370 0.000
Komentár:
Matica vzdialeností hovorí, ktoré krajiny sú si podobné z hľadiska miery
nezamestnanosti (malá vzdialenosť) a ktoré sú odlišné (väčšia
vzdialenosť).
Na základe matice vzdialeností vykonám hierarchické
zhlukovanie pomocou Wardovej metódy
(ward.D2).
Wardova metóda minimalizuje vnútroklastrovú variabilitu a je často
odporúčaná pri zhlukovaní kvantitatívnych premenných.
Všetko (vykreslenie dendrogramu, obdlžníky okolo klastrov aj
priradenie klastrov) dávam do jedného chunka, aby nedochádzalo k chybe
plot.new has not been called yet.
# hierarchické zhlukovanie
hc <- hclust(dist_mat, method = "ward.D2")
# vykreslenie dendrogramu
plot(
hc,
main = "Hierarchické zhlukovanie krajín podľa miery nezamestnanosti (Ward)",
xlab = "",
sub = ""
)
# zvolím počet klastrov
k <- 2
# dokreslím obdlžníky okolo klastrov
rect.hclust(hc, k = k, border = "red")
# priradenie krajín do klastrov
klaster_membership <- cutree(hc, k = k)
klaster_membership
## Czechia Germany Slovakia
## 1 1 2
Teraz spojím informáciu o klastri s pôvodnými (neškálovanými) hodnotami nezamestnanosti:
udaje_clust <- udaje_complete
udaje_clust$klaster <- factor(klaster_membership)
kable(udaje_clust,
caption = "Priradenie krajín do klastrov",
digits = 1) %>%
kable_styling(full_width = FALSE)
| Unemployment | klaster | |
|---|---|---|
| Czechia | 2.6 | 1 |
| Germany | 3.4 | 1 |
| Slovakia | 5.3 | 2 |
Komentár:
- Krajiny v tom istom klastri majú podobnú mieru nezamestnanosti.
- Pri malom počte krajín (tu 3) ide skôr o ilustračný príklad
zhlukovania, ale postup je identický ako pri väčšom počte objektov.
Ďalej vypočítam základné deskriptívne štatistiky miery nezamestnanosti pre jednotlivé klastry.
descriptives <- udaje_clust %>%
dplyr::group_by(klaster) %>%
dplyr::summarise(
n = dplyr::n(),
mean_unemp = mean(Unemployment),
sd_unemp = sd(Unemployment),
min_unemp = min(Unemployment),
max_unemp = max(Unemployment)
)
kable(descriptives,
caption = "Deskriptívne štatistiky miery nezamestnanosti podľa klastrov",
digits = 2) %>%
kable_styling(full_width = FALSE)
| klaster | n | mean_unemp | sd_unemp | min_unemp | max_unemp |
|---|---|---|---|---|---|
| 1 | 2 | 3.0 | 0.57 | 2.6 | 3.4 |
| 2 | 1 | 5.3 | NA | 5.3 | 5.3 |
Komentár:
Z tabuľky vidno, či sú klastry od seba jasne odlíšiteľné – napríklad
jeden klaster môže mať nižšiu priemernú nezamestnanosť a druhý
vyššiu.
Na záver vypočítam rozklad variability:
Najprv si definujem pomocnú funkciu na sumu štvorcov:
ssq <- function(x, m) sum((x - m)^2)
var_names <- colnames(udaje_scaled)
# Celková suma štvorcov (TSS) pre každú premennú
TSS <- sapply(var_names, function(v) {
ssq(udaje_scaled[, v], mean(udaje_scaled[, v]))
})
# Vnútroklastrová suma štvorcov (WSS)
WSS <- sapply(var_names, function(v) {
x <- udaje_scaled[, v]
tapply(x, klaster_membership, function(z) ssq(z, mean(z))) |> sum()
})
# Medziklastrová suma štvorcov (BSS)
BSS <- TSS - WSS
variab_tab <- data.frame(
Variable = var_names,
TSS = TSS,
WSS = WSS,
BSS = BSS,
BSS_over_TSS = BSS / TSS
)
kable(variab_tab,
digits = 3,
caption = "Rozklad variability pre mieru nezamestnanosti") %>%
kable_styling(full_width = FALSE)
| Variable | TSS | WSS | BSS | BSS_over_TSS | |
|---|---|---|---|---|---|
| Unemployment | Unemployment | 2 | 0.166 | 1.834 | 0.917 |
Komentár:
V cvičení som vykonala zhlukovú analýzu prierezových údajov o miere
nezamestnanosti v roku 2024 pre tri krajiny: Czechia, Germany a
Slovakia.
Najprv som z panelových údajov (viaceré roky) vytvorila prierezový
dataset pre jeden rok, čím som splnila podmienku zadania na prierezové
údaje. Potom som premennú štandardizovala, vypočítala maticu
vzdialeností a pomocou Wardovej metódy vykonala hierarchické
zhlukovanie.
Postup v skratke:
Rovnaký postup je možné použiť aj na bohatší dataset s väčším počtom krajín a premenných, kde je zhluková analýza užitočným nástrojom na identifikáciu skupín podobných objektov.