Úvod

V tejto úlohe robím klastrovú (zhlukovú) analýzu, a používam databázu World Happiness Report 2019, ktorú mám uloženú v priečinku udaje ako 2019.csv. Cieľom je zoskupiť krajiny podľa podobnosti v základných socio-ekonomických a zdravotných ukazovateľoch. Týmto spôsobom viem nájsť “podobné” krajiny a pochopiť, ktoré faktory ich robia blízkymi alebo odlišnými.

Nastavenie prostredia

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

library(knitr)
library(kableExtra)
library(ggplot2)
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:kableExtra':
## 
##     group_rows
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(cluster)
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
library(stats)
rm(list = ls())

Načítanie a výber údajov

Pracujem so všetkými krajinami dostupnými v roku 2019. Pre jednoduchosť však ponechám len premenné, ktoré sú dobre interpretovateľné a použiteľné v klastrovej analýze a to:

udaje_raw <- read.csv("udaje/2019.csv", sep = ",", dec = ".", header = TRUE)
names(udaje_raw) <- make.names(names(udaje_raw))

udaje <- udaje_raw[, c("Country.or.region",
                       "Score",
                       "GDP.per.capita",
                       "Social.support",
                       "Healthy.life.expectancy")]

rownames(udaje) <- udaje$Country.or.region
udaje$Country.or.region <- NULL

summary(udaje)
##      Score       GDP.per.capita   Social.support  Healthy.life.expectancy
##  Min.   :2.853   Min.   :0.0000   Min.   :0.000   Min.   :0.0000         
##  1st Qu.:4.545   1st Qu.:0.6028   1st Qu.:1.056   1st Qu.:0.5477         
##  Median :5.380   Median :0.9600   Median :1.272   Median :0.7890         
##  Mean   :5.407   Mean   :0.9051   Mean   :1.209   Mean   :0.7252         
##  3rd Qu.:6.184   3rd Qu.:1.2325   3rd Qu.:1.452   3rd Qu.:0.8818         
##  Max.   :7.769   Max.   :1.6840   Max.   :1.624   Max.   :1.1410

Z-škálovanie premenných

Musím premenné preškálovať, aby boli na rovnakej škále.

udaje_scaled <- scale(udaje)
summary(udaje_scaled)
##      Score          GDP.per.capita    Social.support    Healthy.life.expectancy
##  Min.   :-2.29454   Min.   :-2.2720   Min.   :-4.0403   Min.   :-2.9953        
##  1st Qu.:-0.77494   1st Qu.:-0.7590   1st Qu.:-0.5116   1st Qu.:-0.7331        
##  Median :-0.02479   Median : 0.1377   Median : 0.2095   Median : 0.2633        
##  Mean   : 0.00000   Mean   : 0.0000   Mean   : 0.0000   Mean   : 0.0000        
##  3rd Qu.: 0.69840   3rd Qu.: 0.8217   3rd Qu.: 0.8145   3rd Qu.: 0.6464        
##  Max.   : 2.12188   Max.   : 1.9550   Max.   : 1.3877   Max.   : 1.7171

Boxploty premenných po škálovaní

num_vars <- as.data.frame(udaje_scaled)
num_plots <- ncol(num_vars)

par(mfrow = c(2,2))
par(mar = c(4,4,2,1))

for (col in names(num_vars)) {
  boxplot(num_vars[[col]],
          main = col,
          col = "lightblue",
          horizontal = TRUE)
}

mtext("Boxploty škálovaných premenných (World Happiness 2019)", outer = TRUE, cex = 1.3, font = 2)

Niektoré krajiny majú extrémne hodnoty, ale tie ponechávam pretože ide o reálne rozdiely.

Korelačná matica

Korelačná matica ukazuje, ako spolu jednotlivé premenné súvisia. V mojom prípade sú všetky korelácie stredne vysoké (okolo 0.72–0.84), čo znamená, že premenné medzi sebou súvisia, ale nie príliš silno.

Dôležité je, že žiadna korelácia nepresiahla hodnotu 0.9, čo je hranica, pri ktorej by som už musela jednu premennú vylúčiť (pretože by boli takmer totožné). Keďže tu žiadna premenná túto hranicu nepresiahla, môžem si bez problémov ponechať všetky premenné v ďalšej analýze.

Najsilnejšie súvislosti sú medzi:

Čo dáva aj intuitívny zmysel — bohatšie a zdravšie krajiny majú väčšinou aj vyšší index šťastia.

cor_mat <- cor(udaje_scaled)
round(cor_mat, 2)
##                         Score GDP.per.capita Social.support
## Score                    1.00           0.79           0.78
## GDP.per.capita           0.79           1.00           0.75
## Social.support           0.78           0.75           1.00
## Healthy.life.expectancy  0.78           0.84           0.72
##                         Healthy.life.expectancy
## Score                                      0.78
## GDP.per.capita                             0.84
## Social.support                             0.72
## Healthy.life.expectancy                    1.00

Matica vzdialenosti

Matica vzdialeností ukazuje, ako ďaleko sú od seba krajiny. Je to základný krok klastrovej analýzy, pretože podľa týchto vzdialeností algoritmus zlučuje podobné krajiny. Kedže mám dáta sa vyše ako 100 krajín, vypíšem na ukážku len prvých 10. Krajiny s podobnými hodnotami sú si bližšie, vzdialenejšie krajiny majú protikladné charakteristiky.

dist_mat <- dist(udaje_scaled, method = "euclidean")
as.matrix(dist_mat)[1:10, 1:10]   # výpis prvých 10x10
##               Finland   Denmark    Norway   Iceland Netherlands Switzerland
## Finland     0.0000000 0.1964592 0.4535258 0.3371978   0.3654694   0.5121674
## Denmark     0.1964592 0.0000000 0.2992397 0.2313732   0.2009944   0.3461069
## Norway      0.4535258 0.2992397 0.0000000 0.3101135   0.3337759   0.2396738
## Iceland     0.3371978 0.2313732 0.3101135 0.0000000   0.3609749   0.3894104
## Netherlands 0.3654694 0.2009944 0.3337759 0.3609749   0.0000000   0.2605853
## Switzerland 0.5121674 0.3461069 0.2396738 0.3894104   0.2605853   0.0000000
## Sweden      0.5302072 0.3727102 0.4551738 0.4830257   0.1813002   0.3004991
## New Zealand 0.4671600 0.3575233 0.5214677 0.3401867   0.3271924   0.4316273
## Canada      0.5670453 0.4109969 0.4744478 0.4473830   0.2686413   0.2973733
## Austria     0.6200076 0.4642849 0.5347466 0.5472277   0.2817677   0.3629715
##                Sweden New Zealand    Canada   Austria
## Finland     0.5302072   0.4671600 0.5670453 0.6200076
## Denmark     0.3727102   0.3575233 0.4109969 0.4642849
## Norway      0.4551738   0.5214677 0.4744478 0.5347466
## Iceland     0.4830257   0.3401867 0.4473830 0.5472277
## Netherlands 0.1813002   0.3271924 0.2686413 0.2817677
## Switzerland 0.3004991   0.4316273 0.2973733 0.3629715
## Sweden      0.0000000   0.3243025 0.1594709 0.1039263
## New Zealand 0.3243025   0.0000000 0.2408075 0.3367499
## Canada      0.1594709   0.2408075 0.0000000 0.1437587
## Austria     0.1039263   0.3367499 0.1437587 0.0000000

Najbližšie k sebe majú krajiny ako Fínsko, Dánsko, Švajčiarsko, Holandsko, Island či Švédsko. Je to logické, keďže patria medzi najvyspelejšie štáty a dosahujú veľmi podobné hodnoty vo všetkých sledovaných ukazovateľoch. Napríklad vzdialenosť Fínsko – Dánsko je iba 0.19, čo znamená vysokú podobnosť. Naopak, vzdialenosti okolo 0.5–0.6 už naznačujú výrazné rozdiely medzi krajinami.

Hierarchické zhlukovanie (Wardova metóda)

hc <- hclust(dist_mat, method = "ward.D2")

k <- 3
klastre <- cutree(hc, k = k)

library(factoextra)

fviz_dend(hc,
          k = k,
          cex = 0.25,                       # ešte menšie písmo
          horiz = FALSE,
          k_colors = c("red","blue","darkgreen"),
          main = "Hierarchické zhlukovanie – World Happiness 2019")

Pri vytváraní dendrogramu som najprv použila základný príkaz plot(hc) tak ako v príklade od Vás. Keďže však môj dataset World Happiness 2019 obsahuje výrazne viac krajín (okolo 150), výsledný dendrogram bol nečitateľný – názvy krajín sa prekrývali a nebolo možné určiť klastre. Preto som použila funkciu fviz_dend() z balíka factoextra, ktorá umožňuje zmenšiť veľkosť textu, pridať farby pre jednotlivé klastre a zlepšiť čitateľnosť grafu.Na prvý pohľad je to stále nečítateľné ale po priblížení sa to dá. :) Takto upravený dendrogram je prehľadný a dá sa z neho interpretovať členenie krajín. Pri tomto mi pomohol ChatGPT.

Krajiny sa prirodzene rozdelili do troch veľmi logických klastrov. Prvý klaster(červený) zahŕňa najšťastnejšie a ekonomicky najrozvinutejšie štáty, najmä severské krajiny, Holandsko, Švajčiarsko a Kanadu. Druhý klaster(modrý) predstavuje stredne rozvinuté európske krajiny a niektoré štáty so zmiešaným profilom. Tretí klaster(zelený) tvorí skupina najchudobnejších krajín, prevažne z Afriky a južnej Ázie, s najnižšími hodnotami všetkých sledovaných ukazovateľov. Celkový výsledok dobre vystihuje globálne rozdiely v kvalite života a potvrdzuje, že štáty sa prirodzene zhlukujú podľa socio-ekonomických charakteristík.


Vnútroklastrová a medziklastrová variabilita

ssq <- function(x, m) sum((x - m)^2)

var_names <- colnames(udaje_scaled)

TSS <- sapply(var_names, function(v) ssq(udaje_scaled[, v], mean(udaje_scaled[, v])))

WSS <- sapply(var_names, function(v) {
  x <- udaje_scaled[, v]
  tapply(x, klastre, function(z) ssq(z, mean(z))) |> sum()
})

BSS <- TSS - WSS

ss_table <- data.frame(
  Variable = var_names,
  TSS = TSS,
  WSS = WSS,
  BSS = BSS,
  Prop_Between = BSS / TSS
)

ss_table
##                                        Variable TSS      WSS       BSS
## Score                                     Score 155 41.47753 113.52247
## GDP.per.capita                   GDP.per.capita 155 32.27353 122.72647
## Social.support                   Social.support 155 62.63249  92.36751
## Healthy.life.expectancy Healthy.life.expectancy 155 47.98130 107.01870
##                         Prop_Between
## Score                      0.7324030
## GDP.per.capita             0.7917837
## Social.support             0.5959194
## Healthy.life.expectancy    0.6904432

Na základe hodnoty Prop_Between môžem konštatovať, že najvýraznejšie odlišujú klastre premenné GDP per capita, Score a Healthy life expectancy, zatiaľ čo premenná Social support má najnižšiu separačnú schopnosť. To znamená, že ekonomická úroveň a zdravotný stav sú hlavné faktory, ktoré rozdeľujú krajiny sveta do jednotlivých klastrov v roku 2019.


Centroidy klastrov (priemerné hodnoty)

Z porovnania centroidov jasne vidieť, že klastre reprezentujú tri úrovne rozvoja – vysokú, strednú a nízku – a rozdelenie krajín teda veľmi dobre odráža ich reálnu socio-ekonomickú situáciu.

udaje_centroids <- data.frame(udaje, klaster = klastre)

deskriptiva <- udaje_centroids %>%
  group_by(klaster) %>%
  summarise(
    Score = mean(Score),
    GDP = mean(GDP.per.capita),
    Social = mean(Social.support),
    Health = mean(Healthy.life.expectancy)
  )

deskriptiva
## # A tibble: 3 × 5
##   klaster Score   GDP Social Health
##     <int> <dbl> <dbl>  <dbl>  <dbl>
## 1       1  6.50 1.28   1.44   0.935
## 2       2  5.10 0.842  1.19   0.698
## 3       3  3.98 0.317  0.805  0.383

Záver

V tejto úlohe som pomocou hierarchickej klastrovej analýzy rozdelila krajiny sveta za rok 2019 do troch logických skupín. Ukázalo sa, že najsilnejšie oddeľujúce premenné sú HDP na obyvateľa, sociálna opora a zdravá dĺžka života, čo dáva aj intuitívne zmysel – bohaté krajiny s kvalitným zdravotníctvom tvorili samostatný klaster. Naopak, menej rozvinuté štáty skončili spolu v klusteri s nižšími hodnotami všetkých premenných. Táto analýza ukazuje, že aj jednoduchá klastrová metóda dokáže veľmi dobre identifikovať skupiny podobných krajín na základe socio-ekonomických ukazovateľov a môže byť užitočná pri porovnávaní svetových regiónov alebo plánovaní politík.

Dnešné zadanie ma bavilo a malo aj zaujímavý výsledok. Teším sa na ďalšie. Vanessa