Nezaradené

Ako vytvoriť API v R pomocou knižnice Plumber 150 150 cleandata

Ako vytvoriť API v R pomocou knižnice Plumber

V tomto blogu vám predstavím Plumber – knižnicu v R, ktorá umožňuje jednoducho vytvárať webové API z vašich R skriptov a modelov. Ukážem, ako môžete svoje modely sprístupniť programovo a ako ich nasadiť do produkcie pomocou Dockeru, čím sprístupníte výsledky svojej práce širšej skupine používateľov.

blog

Úvod

Často sa stretávam s tvrdením, že Python je jedinou správnou voľbou pre produkčné nasadenie modelov a aplikácií. R býva označované ako nástroj, ktorého miesto je v akadémii alebo je síce výborný na dátovú analýzu a štatistické výpočty, ale v produkcii nie je použiteľný. Toto tvrdenie však nemusí byť pravdivé ak sa venujete dátovej analýze alebo tradičnému strojovému učeniu. R je v týchto oblastiach silným hráčom vďaka moderným frameworkom ako Tidymodels a mlr3, ktoré nezaostávajú za Pythonom a v oblasti spracovania dát si dovolím povedať, že má dokonca navrch vďaka frameworku tidyverse. Niekto by mohol oponovať, že Python je rýchlejší. Hádajte čo. R ponúka napr. data.table, ktorý je rýchly a ak vám nevadí menší overhead, môžete použiť aj dtplyr, ktorý vám opäť ponúka tidy syntax. Mimochodom, všimli ste si, že Google prišiel s novou syntaxou pre SQL, ktorá používa “pipe operator”, rovnako ako R používa už roky? Škoda, že nikde nespomínajú túto inšpiráciu. Určite by to pomohlo popularizovať R medzi analytikmi a dátovými vedcami.

Ako však zabezpečiť, aby výsledky vašej práce v R boli ľahko dostupné aj kolegom bez nutnosti používať samotné R? Riešením je použitie API. V tomto blogu si predstavíme, ako jednoducho môžeme vytvoriť API pomocou knižnice Plumber. Ukážeme si konkrétny príklad nasadenia XGBoost modelu na predikciu cien bytov, ktorý bude dostupný cez webové rozhranie alebo programovo v kóde v zásade v ktoromkoľvek jazyku.

Čo je Plumber?

Plumber je R knižnica, ktorá umožňuje premeniť R skripty (od jednoduchých funkcií, cez komplexné transformácie až po rôzne objekty) na webové API. Týmto spôsobom môžete jednoducho poskytnúť výsledky vašej práce aj tým používateľom, ktorí nemusia pracovať v R a môžu využívať iné technológie či programovacie jazyky.

Na transformáciu kódu na API typicky používame špeciálne komentáre/anotácie označené pomocou #*, #* @param, #* @post (a iné endpointy, viď. nižšie), #* @serializer a i. Tie definujú správanie API a parametre, ktoré môžeme poskytnúť pri volaní API.

Endpointy

Endpointy sú špeciálne funkcie, ktoré definujú ako bude API reagovať na rôzne HTTP požiadavky. Napríklad, ak chcete vytvoriť endpoint pre GET požiadavku, môžete použiť #* @get /názov. Pre POST požiadavku použijete #* @post /názov. Viac informácií o HTTP metódach nájdete na restapitutorial.

Serializácia

Plumber podporuje rôzne formáty serializácie, ako sú JSON, CSV, HTML a ďalšie. Defaultne je nastavený JSON, ale môžete si zvoliť iný formát pomocou #* @serializer. Napríklad, ak chcete vrátiť odpoveď vo formáte CSV, môžete použiť #* @serializer csv. Medzi ďalšie formáty patria napr. parquet, html, pdf, jpeg, png a iné.

Programové volanie

Okrem tvorby API pomocou anotácií môžete vytvoriť API aj programovo. Na to slúži funkcia pr() (plumber router), ktorá vám umožňuje definovať API pomocou R6 objektov. Tento prístup je užitočný, ak potrebujete väčšiu flexibilitu a kontrolu.

Hooks

Plumber podporuje “hooks”, čiže špeciálne funkcie, ktoré sa vykonávajú pred alebo po spracovaní požiadavky. Tieto funkcie môžu byť použité na rôzne účely, ako napríklad autentifikácia, logovanie alebo spracovanie chýb.

Aktuálne sú podporované nasledujúce hooky: – preroute(data, req, res): vykoná sa pred spracovaním požiadavky – postroute(data, req, res, value): vykoná sa po spracovaní požiadavky – preserialize(data, req, res, value): vykoná sa pred serializáciou odpovede – postserialize(data, req, res, value): vykoná sa po serializácii odpovede

Filtre

Filtre sú špeciálne funkcie, ktoré modifikujú prichádzajúcu požiadavku, vrátia chybu alebo vrátia odpoveď predtým, ako požiadavka dosiahne endpoint. Sú užitočné na spracovanie vstupov, ako je napríklad overenie formátu alebo typov údajov. Rovnako môžu pridávať dodatočné informácie do požiadavky, napr. timestamp alebo unikátne ID relácie.

Každý filter musí obsahovať funkciu forward(). Tá je zodpovedná za predanie kontroly ďalšiemu filtru alebo endpointu. Ak sa táto funkcia nezavolá, predpokladá sa, že požiadavku spracoval sám a žiadny iný filter alebo endpoint nebude spracovávať túto požiadavku.

Kľúčovou vlastnosťou filtrov je, že nie všetky endpointy ich musia použiť.

Ďalšie info

Pre viac informácií o tvorbe API pomocou knižnice Plumber odporúčam navštíviť oficiálnu stránku. V sekcii “Articles” nájdete množstvo užitočných článkov a príkladov, ktoré vám pomôžu lepšie pochopiť, ako Plumber funguje. Okrem základných návodov tam nájdete aj články venujúce sa bezpečnosti, hostingu a nasadeniu API do produkcie.

Praktická ukážka

Tento projekt čiastočne nasledoval postup podľa série blogov od Jafara Aziza. Jeho kód nájdete na GitHube. Hlavný rozdieľ je v tom, že vytvárame len jednu API, zato však komplikovanejšiu, keďže sa jedná o integráciu ML modelu.

Štruktúra projektu

Naša ukážková aplikácia umožňuje predikovať cenu bytu podľa rôznych parametrov, ako je lokalita, rozloha, stav či typ bytu. je to rovnaký model ako sme použili v tomto blogu a Shiny aplikácii. Upozorňujem, že model bol trénovaný na dátach z konca roka 2023 a jeho predikcie sú len orientačné.

Štruktúra nášho projektu vyzerá nasledovne:

.
├── app.R
├── data
│   ├── bundled.RDS
│   ├── certificates.RDS
│   ├── conditions.RDS
│   ├── districts.RDS
│   ├── districts_mapping.RDS
│   ├── index.RDS
│   ├── latlon.RDS
│   ├── municipalities.RDS
│   └── types.RDS
├── docker-compose.yaml
├── Dockerfile
├── helpers
│   ├── logging.R
│   └── validator.R
└── logs
    ├── plumber_20250420_185501.log
    └── plumber_20250421_094015.log

V hlavnom skripte app.R načítavame model aj potrebné dáta (obe z priečinku data na diagrame), definujeme API endpointy a spúšťame samotné API. Na spracovanie vstupov využívame pomocné skripty.
Skript validator.R obsahuje funkcie na validáciu vstupných parametrov, ktoré sú volané v rámci API endpointov. Skript error.R obsahuje funkcie na spracovanie chýb a logovanie.R obsahuje funkcie na logovanie požiadaviek a odpovedí.
Skript logging.R obsahuje funkcie na logovanie požiadaviek a odpovedí. Tieto funkcie sú volané v rámci API endpointov a slúžia na sledovanie správania API a identifikáciu chýb. Na diagrame vidíme príklady .log súborov pod priečinkom “logs”, ktoré sa generujú pri spustení API. Tu treba povedať, že pri použitom deploymente sa tieto logy neukladajú a ich účel bol len pre identifikáciu chýb pri vývoji.

Nasadenie do GCP cez Docker

Pre nasadenie API do produkcie (na Google Cloud Platform) používame Docker, čo nám zaručuje, že aplikácia bude fungovať identicky lokálne aj v produkcii. Použitím docker-compose.yaml a Dockerfile máme jednoduchý spôsob ako API spustiť a spravovať v rôznych prostrediach.

Docker-compose.yaml súbor definuje jednoduchú konfiguráciu pre spustenie API služby v Docker kontajnery. Tento súbor obsahuje aj definíciu siete a portu, na ktorom bude API dostupné. V našom prípade je to port 8000.

version: '3'

services:
  api:
    build: .
    container_name: predict
    volumes:
      - ./:/app
    environment:
      - PORT=${PORT:-8000}
      - HOST=${HOST:-0.0.0.0}
    ports:
      - "8000:8000"

Dockerfile obsahuje inštrukcie na vytvorenie Docker image, ktorý obsahuje všetky potrebné závislosti a knižnice pre spustenie API. Tento image je možné nasadiť na rôzne platformy.

FROM rocker/r-ver:latest

# install os dependencies
RUN apt-get update -qq
RUN apt-get install -y --no-install-recommends \
  git-core \
  libssl-dev \
  libcurl4-gnutls-dev \
  curl \
  libsodium-dev \
  libxml2-dev \
  && rm -rf /var/lib/apt/lists/*

# install pak alternatives to install.packages
RUN Rscript -e "install.packages('pak', repos = sprintf('https://r-lib.github.io/p/pak/stable'))"

# install latest plumber from github main branch
RUN Rscript -e "pak::pkg_install('rstudio/plumber@main')"

# install other R packages
RUN Rscript -e "pak::pkg_install(c('logger','tictoc', 'fs', 'httr', 'dplyr', 'workflows', 'bundle', 'xgboost'))"

# setup workspace
COPY . /app

WORKDIR /app

ENTRYPOINT ["Rscript"]

CMD ["app.R"]

EXPOSE 8000

Image následne vytvoríme pomocou príkazu:

docker compose build --no-cache api

Následne kontajner umiestnime na server, ktorý sme si vybrali na nasadenie. V našom prípade je to Google Cloud Platform.

Zavolanie API

Na úvod malé upozornenie: Prvé zavolanie môže trvať dlhšie kvôli cold startu.

URL

API je teraz možné zavolať rôznymi spôsobmi. Typickým je napr. zavolanie priamo z prehliadača cez URL:

https://appartments-model-api-api-217473566915.europe-central2.run.app/predict?name_nsi=Senec&condition=Novostavba&area=72&provision=0&certificate=A&type=3_i_b

V tomto prípade sme zavolali endpoint /predict s parametrami name_nsi, condition, area, provision, certificate a type. Tieto parametre sú definované v našom API a sú potrebné na vykonanie predikcie. Odpoveď bude vo formáte JSON, ktorý obsahuje predikovanú cenu bytu:

{
  "predicted_price": 203338.1719
}

Programové volanie

Druhým, praktickejším, spôsobom je zavolanie API programovo. Môžete použitiť akýkoľvek jazyk, ktorý podporuje HTTP požiadavky. V nasledujúcom príklade ostaneme v R, ale rovnako to bude fungovať aj v Pythone, Jave, C#, PHP a iných jazykoch. Pre účely demonštrácie použijeme primárne knižnice httr2 a shiny. V Quarto súbore môžeme vytvoriť jednoduchú aplikáciu, ktorá nám umožní zadať parametre a získať predikciu ceny bytu.

Načítanie knižníc a dát
library(bslib)
library(bsicons)
library(httr2)
library(dplyr)
library(shiny)
library(shinybusy)

mun_list <- readRDS("data/municipalities.RDS")
cond_list <- readRDS("data/conditions.RDS")
cert_list <- readRDS("data/certificates.RDS")
type_list <- data.frame(
  type = c("1-izbový byt", "2-izbový byt", "3-izbový byt", "4-izbový byt", "5-izbový byt"),
  id = c("1_i_b", "2_i_b", "3_i_b", "4_i_b", "5_i_b")
)
prov_list <- data.frame(
  prov = c("Áno", "Nie"),
  id = c(1, 0)
)
UI
layout_sidebar(
  height = 700,
  width = 700,
  sidebar =  sidebar(
    shiny::selectizeInput(
      'select_mun', 
      'Obec', 
      choices = mun_list$Obec,
      selected = mun_list$Obec[1],
      multiple = FALSE
    ),
    shiny::selectizeInput(
      'select_cond',
      'Stav',
      choices = cond_list$Stav,
      selected = cond_list$Stav[1],
      multiple = FALSE
    ),
    shiny::selectizeInput(
      'select_cert', 
      'Certifikát', 
      choices = cert_list$Certifikát,
      selected = cert_list$Certifikát[1],
      multiple = FALSE
    ),
    shiny::selectizeInput(
      'select_type', 
      'Typ bytu', 
      choices = type_list$type,
      selected = type_list$type[1],
      multiple = FALSE
    ),
    shiny::selectizeInput(
      'select_prov', 
      'Provízia v cene', 
      choices = prov_list$prov,
      selected = prov_list$prov[1],
      multiple = FALSE
    ),
    shiny::sliderInput(
      'area',
      'Rozloha (m2)',
      min = 50,
      max = 150,
      value = 70
    ),
  shiny::actionButton(
      "submit",
      "Zavolať API",
      icon = shiny::icon("calculator"),
      class = "btn-primary"
    )
  ),
  use_busy_spinner(spin = "flower",
                   color = "primary"),
  value_box(
    title = "Predikovaná cena",
    value = textOutput("prediction"),
    showcase = bs_icon("house"),
    max_height = "100px",
    width_full_screen = "4oopx"
  )
)
Server
# URL API
api_url <- "https://appartments-model-api-api-217473566915.europe-central2.run.app/predict"

# Reaktívna funkcia pre získanie predikcie z API
predicted_price <- reactiveVal(NULL)

observeEvent(input$submit, {
  
  show_spinner()
  
  req(input$select_mun, input$select_cond, input$area, input$select_cert, input$select_type, input$select_prov)

type_valid <- type_list |> 
    filter(type == input$select_type) |> 
    pull(id)

provision_numeric <- prov_list |> 
    filter(prov == input$select_prov) |> 
    pull(id)

  response <- request(api_url) |> 
    req_url_query(
      name_nsi    = input$select_mun,
      condition   = input$select_cond,
      area        = input$area,
      provision   = provision_numeric,
      certificate = input$select_cert,
      type        = type_valid
    ) |> 
    req_perform() |> 
    resp_body_json()
  
  hide_spinner()

  predicted_price(response$predicted_price[1])

})


output$prediction <- renderText({
  req(predicted_price())
  paste0(format(round(predicted_price(), 0), big.mark = " ", decimal.mark = ","), 
        " €")
})

Aplikácia je jednoduchá a umožňuje zadať parametre pre predikciu ceny bytu. Po kliknutí na tlačidlo “Zavolať API” sa zavolá API a zobrazí sa predikovaná cena bytu. Vyskúšať si ju môžete na Shinyapps.io.

UI aplikácie

Vytvorenie takejto mini aplikácie je veľmi jednoduché a rýchle (otázka minút).

Záver

R má svoje silné stránky, ktoré nie je potrebné obmedzovať len na analýzu. S využitím vhodných knižníc ako je Plumber (prípadne Plumber2, ktorý je v aktívnom vývoji a dá sa inštalovať z GitHubu) môžeme jednoducho a efektívne sprístupniť transormačné pipeline-y, ML modely, generátory reportov a mnoho ďalších dátových produktov do vnútra firmy alebo aj širšej verejnosti. Druhý benefit môže byť oddelenie business logiky od aplikácie, čo môže byť užitočné pri vývoji a údržbe aplikácií.

Či už si zvolíte na sprístupmenie API URL alebo väčšiu aplikáciu, Plumber vám ponúka flexibilitu a jednoduchosť.

V produkcii sa teda netreba báť použiť R. Mýty o pomalosti tohto jazyka vychádzajú skôr z nevhodných programátorských praktík užívateľov (ktorých báza, je tvorená akademikmi a odborníkmi v oblasti life sciences bez znalostí z oblasti programovania) ako z nedostatkov samotného jazyka.

Ako zrýchliť XGBoost v R: Benchmark trénovania modelu na CPU vs. GPU 150 150 cleandata

Ako zrýchliť XGBoost v R: Benchmark trénovania modelu na CPU vs. GPU

cpu-vs-gpu-blog

Ako rýchlo dokážete vytrénovať model na veľkých datasetoch? Toto je otázka, ktorú si kladie mnoho analytikov a data scientistov, keď začínajú pracovať s pokročilými algoritmami strojového učenia, ako je XGBoost. V tomto článku si ukážeme, ako vytvoriť klasifikačný model pomocou XGBoost v R a porovnáme si dĺžku výpočtu pri použití CPU a GPU.

Štandardná verzia knižnice XGBoost na CRAN však nepodporuje parameter device = “cuda”. Preto je potrebné nainštalovať špeciálnu verziu XGBoostu – buď skompilovať z repozitára na GitHube, alebo využiť poskytovaný inštalačný balík (napríklad pre Windows takto):

Inštalácia xgboost
options(timeout = 1200)
xgboost_url <- "https://s3-us-west-2.amazonaws.com/xgboost-nightly-builds/release_2.0.0/xgboost_r_gpu_win64_82d846bbeb83c652a0b1dff0e3519e67569c4a3d.tar.gz"
install.packages(xgboost_url, repos = NULL, type = "source")

CPU vs GPU

Na veľkých datasetoch môže trénovanie modelov trvať hodiny, ak nie dni, najmä na bežných procesoroch (CPU). Moderné grafické karty (GPU) od spoločnosti Nvidia však umožňujú paralelné spracovanie dát, čo dramaticky zrýchľuje niektoré výpočtové operácie.

CPU je ako pracovník, ktorý rieši úlohy sekvenčne, zatiaľ čo GPU je tím tisícov pracovníkov, ktorí dokážu riešiť mnohé úlohy naraz.

Ešte predtým, než prejdeme k modelovaniu, môžeme si zistiť, aký hardvér vlastne používame.

AMD Ryzen 9 7900X je vysoko výkonný desktopový procesor s 12 fyzickými jadrami (24 vláknami), ktorý je všeobecne považovaný za high-end/výkonný segment pre multivláknové operácie (aktuálne je dostupná už novšia generácia AMD procesorov). K nemu je 67.8 GB RAM, čo dáva dostatočnú rezervu na spracovanie stredne veľkých až väčších datasetov. Grafická karta Nvidia RTX 4060Ti s 8 GB VRAM sa radí do strednej až vyššej strednej triedy, no pri veľmi rozsiahlych datasetoch môže byť 8 GB VRAM limitujúce. Napriek tomu dokáže pri bežných projektoch a primerane veľkých dátach výrazne zrýchliť trénovanie XGBoost modelov v porovnaní s CPU. Viac info nájdete v staršom blogu.

1. Načítanie knižníc a príprava prostredia

Na začiatku si načítame potrebné balíky. Je dobré nastaviť aj niektoré globálne možnosti, napríklad options(scipen = 999), aby sme obmedzili vedecký zápis čísel.

Knižnice
options(scipen = 999)
library(data.table)
library(readr)
library(xgboost)
library(tidymodels)
library(dplyr)
library(stringr)
library(doParallel)
library(tictoc)

data.table nám umožní rýchle nahratie .csv. tidymodels je framework pre tvorbu a ladenie modelov. xgboost je samotná implementácia gradient boosting algoritmov. tictoc nám zmeria čas operácie (funkcie tic() a toc())

2. Načítanie, čistenie a rozdelenie dát

Začneme s dvoma datasetmi: train.csv a test.csv. Oba súbory sú dostupné na Kaggle.

Dátový stĺpec id odstránime (neobsahuje relevantné informácie pre model). Premennú class transformujeme tak, aby hodnota “e” mala label 0, a “p” label 1. Prázdne stringy (textové premenné) nahradíme za “missing”, pretože chceme explicitne ošetriť chýbajúce hodnoty.

Príprava dát
## data prep ----
train <- data.table::fread("data/train.csv") |> 
  select(-id) |> 
  mutate(class = factor(class, levels = c("p", "e"), labels = c(1, 0))) |> 
  mutate(across(where(is.character), ~ if_else(. == "", "missing", .)))

dim(train)
[1] 3116945      21

Finálny trénovací dataset má 21 stĺpcov vrátane triedy, ktorú budeme predikovať a 3 116 945 záznamov.

Nasleduje klasické rozdelenie pomocou initial_split z rsample: prop = 0.7 znamená, že 70 % záznamov ide do trénovacej množiny a 30 % do testovacej, strata = class zachováva približný pomer tried v oboch množinách.

Pri ladení modelu použijeme 10-násobnú cross validáciu.

Rozdelenie dát
set.seed(123)
split <- initial_split(train, prop = 0.7, strata = class)

train_set <- training(split)
test_set <- testing(split)

set.seed(123)
folds <- vfold_cv(train_set, strata = class)

3. Pre-Processing

V recipe() si definujeme jednotlivé kroky v tzv. recipe pipeline.

step_other() s threshold = 0.005 zlúči veľmi vzácne kategórie (s podielom < 0.5 %) do kategórie “other”. step_string2factor() prevedie stringové atribúty na faktory. step_dummy() vytvorí dummy premenné z faktorov.

Nastavenie pre-processingu
recipe <- recipe(class ~ ., data = train_set) |> 
  step_other(all_nominal_predictors(), threshold = 0.005) |> 
  step_string2factor(all_nominal_predictors()) |>
  step_dummy(all_nominal_predictors())

4. Definícia XGBoost modelov (CPU a GPU)

4.1. Základné XGBoost parametre

  • trees = 1000: Počet stromov.
  • tree_depth = tune(): Hĺbka stromu, ktorú budeme ladiť.
  • min_n = tune(): Minimálny počet záznamov v koncovom uzle stromu (v XGBoost často min_child_weight).
  • loss_reduction = tune(): (v XGBoost označované ako gamma) – ovplyvňuje, o koľko sa musí znížiť chyba, aby došlo k deleniu uzla.
  • sample_size = tune(): (v XGBoost subsample) – podiel vzoriek použitých pre každý strom.
  • mtry = tune(): (v XGBoost colsample_bynode) – podiel stĺpcov vyberaných pri každom delení.
  • learn_rate = tune(): (v XGBoost eta) – reguluje rýchlosť učenia.

Rozdiel medzi CPU a GPU modelmi: Zásadné je device = “cuda” a tree_method = “hist”. Týmito parametrami vravíme xgboostu, že chceme použiť GPU. Nastavujeme nthread = 12, aby sme využili všetky dostupné jadrá CPU.

4.2. Model pre CPU

Definovanie CPU modelu
xgb_cpu <- boost_tree(
  trees = 1000,
  tree_depth = tune(), min_n = tune(),
  loss_reduction = tune(),                     ## first three: model complexity
  sample_size = tune(), mtry = tune(),         ## randomness
  learn_rate = tune()                          ## step size
) |> 
  set_engine("xgboost", nthread = 12) |> 
  set_mode("classification")

4.3. Model pre GPU

Definovanie GPU modelu
xgb_gpu <- boost_tree(
  trees = 1000,
  tree_depth = tune(), min_n = tune(),
  loss_reduction = tune(),                     ## first three: model complexity
  sample_size = tune(), mtry = tune(),         ## randomness
  learn_rate = tune()                          ## step size
) |> 
  set_engine("xgboost", device = "cuda", tree_method = "hist", nthread = 12) |> 
  set_mode("classification")

5. Workflows

V tidymodels je workflow elegantný spôsob, ako zlúčiť recept a model:

Vytvorenie workflows
xgb_cpu_wf <- workflow() |> 
  add_recipe(recipe) |> 
  add_model(xgb_cpu)

xgb_gpu_wf <- workflow() |> 
  add_recipe(recipe) |> 
  add_model(xgb_gpu)

Aby sme mohli ladiť hyperparametre, vytvoríme si ešte bayes_param objekt. Použijeme finalize(mtry(), train_set), aby sme odhadli maximálnu hodnotu mtry na základe počtu stĺpcov.

Extrakcia hyperparametrov
bayes_param <- xgb_gpu_wf %>% 
  extract_parameter_set_dials() %>% 
  update(mtry = finalize(mtry(), train_set))

6. Bayesovské ladenie a meranie času

Ladenie bude prebiehať v 6 iteráciách (parametrizovaných v iter = 6). Ide len o ukážku, v reálnom projekte by sme spravidla volili viac iterácií (10, 20, či viac), aby sme dôkladnejšie preskúmali priestor parametrov.

6.1. CPU – tune_bayes

Tuning CPU modelu
tic()
set.seed(234)
cpu_xgb_res <- tune_bayes(
  xgb_cpu_wf,
  param_info = bayes_param,
  resamples = folds, 
  iter = 6
)
toc()
# 24278.11 sec elapsed

6.2. GPU – tune_bayes

Tuning GPU modelu
tic()
set.seed(345)
gpu_xgb_res <- tune_bayes(
  xgb_gpu_wf,
  param_info = bayes_param,
  resamples = folds, 
  iter = 6
)
toc()
# 7345.68 sec elapsed

Porovnanie času výpočtu

  • CPU: ~ 6 hodín 45 minút
  • GPU: ~ 2 hodiny

GPU model je teda približne 3x rýchlejší, čo predstavuje významnú úsporu času pri práci na veľkých datasetoch. V praxi ešte záleží na type GPU, verzii CUDA, atď.

7. Výber najlepších parametrov a finálny model

Po skončení hyperparameter tuningu si môžeme pozrieť metriky cez collect_metrics(), a vybrať najlepšie nastavenia napr. na základe metriky roc_auc.

Výsledné CPU metriky
metrics_cpu <- collect_metrics(cpu_xgb_res)
best_cpu <- select_best(cpu_xgb_res, metric = "roc_auc")

cpu_roc_auc <- metrics_cpu |> 
  filter(.metric == "roc_auc") |> 
  slice_max(mean) |> 
  pull(mean)

Pre CPU model je výsledná hodnota 0.9971878.

Výsledné GPU metriky
metrics_gpu <- collect_metrics(gpu_xgb_res)
best_gpu <- select_best(gpu_xgb_res, metric = "roc_auc")

gpu_roc_auc <- metrics_gpu |> 
  filter(.metric == "roc_auc") |> 
  slice_max(mean) |> 
  pull(mean)

Pre GPU je to 0.9972345.

GPU model nielen že trénuje rýchlejšie, ale dosahuje aj lepšiu presnosť. Je to však veľmi individuálne, závisí od datasetu i parametrov.

Zhrnutie

Čo sme videli?

  • XGBoost sa dá používať na CPU aj GPU pomocou jednoduchých parametrov (device = “cuda”, tree_method = “hist”).
  • Čas výpočtu môže klesnúť až na zlomok, ak máme vhodnú GPU a väčší dataset.
  • Pri ladení parametrov sme použili Bayesovskú optimalizáciu, ktorá je síce efektívnejšia vo vyhľadávaní správnych hyperparametrov, ale je aj výpočtovo náročnejšia než jednoduchšie metódy.

Praktické tipy a nuansy

  • Pamäť GPU môže byť limitujúca. Veľké datasety nemusia vojsť do GPU pamäte.
  • Overheads: Pri relatívne malých datasetoch môže byť efekt GPU nižší alebo dokonca negatívny pre “overheads” spojené s kopírovaním dát medzi CPU a GPU.
  • Data pre-processing: Prechod na GPU je nápomocný hlavne pri trénovaní modelu, ale pre-processing zostáva často na CPU. Ak máte rozsiahlu prípravu dát, toto stále môže byť “bottleneck”. Aj z tohto dôvodu ponechávame nthreads na dostatočne vysokej hodnote.
  • Viac iterácií v Bayesovskej optimalizácii obvykle pomôže presnejšie nájsť najlepšie hyperparametre.

Záver

Modelovanie s XGBoost algoritmom na GPU môže drasticky skrátiť čas trénovania oproti CPU, najmä pri veľkých datasetoch. Ak je to aj Váš prípad a navyše pravidelne pracujete so zložitými modelmi, GPU je dlhodobou investíciou, ktorá šetrí čas a zvyšuje efektivitu práce. Pre menšie projekty však bude postačujúci aj výkon moderného CPU.

Tesla Stock Plunge: How Controversy and Market Trends Impact Investors 150 150 cleandata

Tesla Stock Plunge: How Controversy and Market Trends Impact Investors

In this blog, I explore the impact of Elon Musk’s controversial gesture on Tesla’s stock performance. I analyze it using the statistical method Causal Impact, which estimates the effect of the event by comparing it to a counterfactual scenario. The results highlight how significant this effect was in the context of the broader tech stock sell-off.

Tesla stocks analysis

Tesla stocks analysis

In recent weeks (this blog is written in mid-March 2025), we have been experiencing a sell-off in tech stocks (though not exclusively). While this is driven by a complex mix of factors, many are tied to events happening in the U.S. In particular, Trump’s policies have increased uncertainty for businesses, consumers, and investors.

n this blog, we will focus on one specific event and its impact on Tesla’s stock performance compared to selected tech and car manufacturing companies. We explore the effect of Musk’s controversial gesture. The analysis leverages the tidyquant package to retrieve stock prices from Yahoo Finance and the CausalImpact package to estimate the event’s effect based on counterfactual outcomes. The goal is to assess what portion of Tesla’s stock decline can potentially be attributed to reactions following the event. We acknowledge that stock prices are influenced by numerous factors, and this analysis is a simplification. Additionally, after this event, Musk made several more controversial statements and actions that may have also influenced Tesla’s stock price.

Disclaimer: I am not an economist, and this is a quick analysis using the mentioned methods.

Data overview

The chart below displays the stock prices of selected companies. The line color represents the type of company—tech (blue), car manufacturing (green), and Tesla (red). The vertical dashed line marks the event date. It is evident that Tesla’s stock price is more volatile than that of other companies, with a more pronounced decline.

The tech stocks used for comparison as control variables include: Apple (AAPL), Microsoft (MSFT), NVIDIA (NVDA), Amazon (AMZN), Meta (META), Alphabet (GOOG), Broadcom (AVGO), and Oracle (ORCL).

The car manufacturing stocks used as control variables include: General Motors (GM), Ford (F), Toyota (TM), Stellantis (STLA), Honda (HMC), and Ferrari (RACE).

Causal Impact analysis

Causal Impact is a statistical method used to estimate the causal effect of an event (or intervention) on a time series. It is based on a Bayesian structural time-series model, which estimates the counterfactual (i.e., what would have happened without the event) and compares it to observed data. The counterfactual is derived using a set of control variables selected based on the data. The difference between the observed and counterfactual data represents the estimated effect of the event. This model assumes the effect of the intervention remains constant over time.

The following chart illustrates the estimated impact of the event on Tesla’s stock price. The the solid black line represents the observed data, dashed blue line represents the counterfactual (what would have happened without the event), and the shaded area represents the 95% confidence interval. Since the two lines are very close to each other during the pre-event period, we can assume that the model is well specified.

The model estimates that the event had a negative impact on Tesla’s stock price. The estimated effect is approximately -16% with a 95% confidence interval of [-23%, -8%]. The probability of obtaining this effect by chance is very low (Bayesian one-sided tail-area probability p = 0.001), meaning the causal effect is statistically significant. On the last available date, the estimated effect is -127 USD compared to what we would expect.

Posterior inference {CausalImpact}

                         Average         Cumulative    
Actual                   335             12724         
Prediction (s.d.)        408 (19)        15507 (730)   
95% CI                   [365, 441]      [13857, 16774]
                                                       
Absolute effect (s.d.)   -73 (19)        -2783 (730)   
95% CI                   [-107, -30]     [-4050, -1133]
                                                       
Relative effect (s.d.)   -18% (4%)       -18% (4%)     
95% CI                   [-24%, -8.2%]   [-24%, -8.2%] 

Posterior tail-area probability p:   0.00118
Posterior prob. of a causal effect:  99.88249%

For more details, type: summary(impact, "report")

Summary

The analysis suggests that the event on January 20, 2025, and the subsequent reactions had a significant negative impact on Tesla’s stock price. However, this analysis is based on a simplified model, and stock prices are influenced by many factors. The model assumes that the effect of the event remains constant over time, which may not hold true in reality. Further improvements could be made by incorporating additional control variables or using a more customized model.

It is also reasonable to assume that Musk’s subsequent controversial actions and statements contributed to further fluctuations in Tesla’s stock price.

EDA časových radov: Ako odhaliť vzory skryté v čase 150 150 cleandata

EDA časových radov: Ako odhaliť vzory skryté v čase

V tomto blogu sa pozriem na EDA časových radov – kľúčový prvý krok pri práci s týmito dátami. Preskúmam rôzne metódy, ako dekompozícia, vizualizácia, lagované hodnoty, diferenciácia a detekcia anomálií, ktoré pomáhajú odhaliť vzory skryté v čase.

eda_time_series_analysis

Úvod

Tento dokument slúži ako sprievodca pre exploratívnu analýzu dát (EDA) a analýzu časových radov (TS – time series) s použitím ekosystému tidyverts v R. Cieľom je predstaviť kroky potrebné na prípravu, transformáciu a analýzu časových radov s dôrazom na vizualizácie, dekompozíciu a detekciu anomálií. Všetky príklady využívajú syntetické dáta zahŕňajúce mesačné predaje od roku 2016 do septembra 2024.

Načítanie knižníc a dát

Kód
library(tsibble)
library(fable)
library(fabletools)
library(feasts)
library(readr) # data load
library(openxlsx) # data load
library(skimr) # EDA
library(ggplot2) # visualization
library(lubridate) # time functions
library(dplyr) # data manipulation
library(tidyr) # fill
library(plotly) # interactive visualization
library(cluster) # kmeans clustering of TS
library(priceR) # exchange rates
library(janitor) # clean_names()
library(anomalize) # anomaly detection
#library(tsfeatures)
library(patchwork) # plots alignment


options(scipen = 100)
options(digits = 5)

theme_custom <- theme(
  text = element_text(size = 12),
  panel.grid = element_blank(),
  panel.grid.major.y = element_line(colour = "#e3e1e1",
                                    linetype = 2),
  panel.border = element_blank(),
  panel.background = element_blank(),
  plot.title.position = 'plot',
  legend.position = 'top',
  legend.title = element_blank()
)

theme_set(theme_minimal() + theme_custom)

set.seed(1)
# sales data
data <- read_rds("data/dummy_data_adj.RDS") |> select(-daily_sales)
cur_PLN <- read_rds("data/cur_PLN.RDS")
cur_CZK <- read_rds("data/cur_CZK.RDS")
# all dates
all_dates <- data %>% 
  select(date) %>% 
  distinct() 
# CPI euro zone
CPI_eur <- read_csv("data/CPI euro zone.csv") |> 
  clean_names() |> 
  mutate(date = ceiling_date(date, "month") - 1)
colnames(CPI_eur) <- c('date','CPI_euro')
# CPI Poland
CPI_poland <- all_dates |> 
  left_join(read_csv("data/CPI poland.csv") |> 
  clean_names(),
  by = join_by(date),
  keep = FALSE) |> 
  mutate(date = ceiling_date(date, "month") - 1) |> 
  arrange(date)  |> 
  fill(2, .direction = "down")
colnames(CPI_poland) <- c('date','CPI_poland')
# CPI Czech Republic
CPI_czech_rep <- read_csv("data/CPI czech rep.csv") |> 
  clean_names() |> 
  mutate(date = ceiling_date(date, "month") - 1)
colnames(CPI_czech_rep) <- c('date','CPI_czech')

Prehľad dát

Dataset obsahuje:

  • Dátum: Mesačné údaje od roku 2016 po september 2024 (105 mesiacov).
  • Kategorické premenné: Krajina (3 krajiny), Divízia (2 divízie), Kanál (3 kanály), Produktová skupina (6 skupín).
  • Číselné premenné: Predaje a upravené predaje.

Na rýchle zhrnutie dát použijeme knižnicu skimr:

Kód

skim(data)
Data summary
Name data
Number of rows 5670
Number of columns 6
_______________________
Column type frequency:
Date 1
character 4
numeric 1
________________________
Group variables None

Variable type: Date

skim_variable n_missing complete_rate min max median n_unique
date 0 1 2016-01-01 2024-09-01 2020-05-01 105

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
country 0 1 2 2 0 3 0
division 0 1 6 9 0 2 0
channel 0 1 3 6 0 3 0
product_group 0 1 3 11 0 6 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
sales 0 1 433618 835656 142.8 23204 68880 431096 8016713 ▇▁▁▁▁

Overenie pravidelnosti a úplnosti dát

Kód
# Pravidelnosť podľa krajiny
data |> group_by(country) |> skim()
Data summary
Name group_by(data, country)
Number of rows 5670
Number of columns 6
_______________________
Column type frequency:
Date 1
character 3
numeric 1
________________________
Group variables country

Variable type: Date

skim_variable country n_missing complete_rate min max median n_unique
date CZ 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK 0 1 2016-01-01 2024-09-01 2020-05-01 105

Variable type: character

skim_variable country n_missing complete_rate min max empty n_unique whitespace
division CZ 0 1 6 9 0 2 0
division PL 0 1 6 9 0 2 0
division SK 0 1 6 9 0 2 0
channel CZ 0 1 3 6 0 3 0
channel PL 0 1 3 6 0 3 0
channel SK 0 1 3 6 0 3 0
product_group CZ 0 1 3 11 0 6 0
product_group PL 0 1 3 11 0 6 0
product_group SK 0 1 3 11 0 6 0

Variable type: numeric

skim_variable country n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
sales CZ 0 1 1183321 1114885 17362.00 421734.5 883945 1587691 8016713 ▇▂▁▁▁
sales PL 0 1 87224 82084 223.55 25601.0 61161 115520 506350 ▇▂▁▁▁
sales SK 0 1 30309 29075 142.80 9778.5 22315 40390 195893 ▇▂▁▁▁
Kód

# Úplnosť na najdetailnejšej úrovni
data |> group_by(country, product_group) |> skim()
Data summary
Name group_by(data, country, p…
Number of rows 5670
Number of columns 6
_______________________
Column type frequency:
Date 1
character 2
numeric 1
________________________
Group variables country, product_group

Variable type: Date

skim_variable country product_group n_missing complete_rate min max median n_unique
date CZ Accessories 0 1 2016-01-01 2024-09-01 2020-05-01 105
date CZ Components 0 1 2016-01-01 2024-09-01 2020-05-01 105
date CZ Monitors 0 1 2016-01-01 2024-09-01 2020-05-01 105
date CZ Notebooks 0 1 2016-01-01 2024-09-01 2020-05-01 105
date CZ PCs 0 1 2016-01-01 2024-09-01 2020-05-01 105
date CZ Software 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL Accessories 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL Components 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL Monitors 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL Notebooks 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL PCs 0 1 2016-01-01 2024-09-01 2020-05-01 105
date PL Software 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK Accessories 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK Components 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK Monitors 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK Notebooks 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK PCs 0 1 2016-01-01 2024-09-01 2020-05-01 105
date SK Software 0 1 2016-01-01 2024-09-01 2020-05-01 105

Variable type: character

skim_variable country product_group n_missing complete_rate min max empty n_unique whitespace
division CZ Accessories 0 1 6 9 0 2 0
division CZ Components 0 1 6 9 0 2 0
division CZ Monitors 0 1 6 9 0 2 0
division CZ Notebooks 0 1 6 9 0 2 0
division CZ PCs 0 1 6 9 0 2 0
division CZ Software 0 1 6 9 0 2 0
division PL Accessories 0 1 6 9 0 2 0
division PL Components 0 1 6 9 0 2 0
division PL Monitors 0 1 6 9 0 2 0
division PL Notebooks 0 1 6 9 0 2 0
division PL PCs 0 1 6 9 0 2 0
division PL Software 0 1 6 9 0 2 0
division SK Accessories 0 1 6 9 0 2 0
division SK Components 0 1 6 9 0 2 0
division SK Monitors 0 1 6 9 0 2 0
division SK Notebooks 0 1 6 9 0 2 0
division SK PCs 0 1 6 9 0 2 0
division SK Software 0 1 6 9 0 2 0
channel CZ Accessories 0 1 3 6 0 3 0
channel CZ Components 0 1 3 6 0 3 0
channel CZ Monitors 0 1 3 6 0 3 0
channel CZ Notebooks 0 1 3 6 0 3 0
channel CZ PCs 0 1 3 6 0 3 0
channel CZ Software 0 1 3 6 0 3 0
channel PL Accessories 0 1 3 6 0 3 0
channel PL Components 0 1 3 6 0 3 0
channel PL Monitors 0 1 3 6 0 3 0
channel PL Notebooks 0 1 3 6 0 3 0
channel PL PCs 0 1 3 6 0 3 0
channel PL Software 0 1 3 6 0 3 0
channel SK Accessories 0 1 3 6 0 3 0
channel SK Components 0 1 3 6 0 3 0
channel SK Monitors 0 1 3 6 0 3 0
channel SK Notebooks 0 1 3 6 0 3 0
channel SK PCs 0 1 3 6 0 3 0
channel SK Software 0 1 3 6 0 3 0

Variable type: numeric

skim_variable country product_group n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
sales CZ Accessories 0 1 666039 425783.5 76791.00 151481.8 753222 974967 1600736 ▇▂▇▅▂
sales CZ Components 0 1 611579 556714.7 17362.00 62311.0 475303 1132971 1911453 ▇▂▃▃▁
sales CZ Monitors 0 1 1164950 909263.7 106864.00 225066.2 1100832 1804482 3620145 ▇▅▃▂▁
sales CZ Notebooks 0 1 2001212 1705874.3 194954.00 534365.7 1629913 2857594 8016713 ▇▅▁▁▁
sales CZ PCs 0 1 1923540 1047222.3 446793.00 834311.5 2022042 2583798 5887929 ▇▇▃▁▁
sales CZ Software 0 1 732608 362912.3 65362.00 467194.5 766223 958775 1725191 ▅▆▇▃▁
sales PL Accessories 0 1 78044 51826.0 8974.00 23275.9 79225 111939 241820 ▇▇▅▂▁
sales PL Components 0 1 30040 28792.4 223.55 8053.0 18273 46259 123354 ▇▂▂▁▁
sales PL Monitors 0 1 83086 71495.8 6584.10 30301.5 61357 106836 335074 ▇▂▁▂▁
sales PL Notebooks 0 1 86742 72731.1 10958.20 33772.1 58830 123400 350005 ▇▂▁▁▁
sales PL PCs 0 1 187843 103835.2 40870.00 95534.7 178289 246367 506350 ▇▇▅▂▁
sales PL Software 0 1 57589 37629.3 10308.00 23788.0 45353 90604 158629 ▇▅▂▂▁
sales SK Accessories 0 1 19315 11660.1 2658.80 5078.0 22104 28486 45877 ▇▂▇▅▁
sales SK Components 0 1 11333 10258.7 142.80 2873.5 6852 18190 49780 ▇▃▂▁▁
sales SK Monitors 0 1 37321 22694.9 3903.20 12826.0 39531 53260 92098 ▇▃▆▃▂
sales SK Notebooks 0 1 42568 37129.4 4176.90 15323.9 29436 55498 184205 ▇▃▁▁▁
sales SK PCs 0 1 56910 35174.6 12548.00 27890.5 48991 73774 195893 ▇▅▂▁▁
sales SK Software 0 1 14408 8207.1 1457.75 6910.4 13659 21062 34416 ▇▅▆▅▂

Čistenie a transformácia dát

Cieľom je upraviť dáta pre analýzu časových radov:

  • Upraviť predaje podľa inflácie a výmenných kurzov. Táto úprava umožní lepšie porovnávanie predajov v rôznych časových obdobiach a krajinách. Inflácia ovplyvňuje nominálne hodnoty predajov, a preto ich úprava umožní lepšie pochopiť reálny rast či pokles predaja. Prepočet na rovnaký základ zabezpečí, že časový rad nebude ovplyvnený menovými výkyvmi.
  • Prekonvertovať predaje na jednotnú menu (EUR). Vďaka tomuto kroku môžeme vykonať konzistentnú analýzu predajov v rôznych krajinách na jednotnej škále.
  • Stabilizovať rozptyl pomocou logaritmickej transformácie. Pomáha redukovať extrémne hodnoty, čím znižuje vplyv sezónnych výkyvov a veľkých rozdielov medzi nízkymi a vysokými predajmi. Okrem toho premieňa multiplikatívnu sezónnosť na aditívnu, čo uľahčuje analýzu a modelovanie časových radov. Stabilizácia rozptylu je dôležitá pre modely ako ARIMA alebo ETS, ktoré vyžadujú približne stacionárne dáta.
  • Odstránenie nepotrebných stĺpcov a transformácia na formát tsibble.
Kód

data_cleaned <- data |>
  mutate(
    # Konverzia dátumu na posledný deň v mesiaci
    date = ceiling_date(as.Date(date), "month") - 1
  ) |>
  # Pripojenie dát o výmennom kurze a CPI
  left_join(cur_CZK, by = "date") |>
  left_join(cur_PLN, by = "date") |>
  left_join(CPI_eur, by = "date") |>
  left_join(CPI_czech_rep, by = "date") |>
  left_join(CPI_poland, by = "date") |>
  mutate(
    # Konverzia date na rok-mesiac (yearmonth) pre TS
    date = yearmonth(date),
    # Konverzia predajov (sales) do EUR
    sales_EUR = round(case_when(
      country == "PL" ~ sales * PLN,
      country == "CZ" ~ sales * CZK,
      TRUE ~ sales
    )),
    # Očistenie predajov o infláciu pomocou CPI
    sales_EUR_CPI_adj = round(case_when(
      country == "PL" ~ sales_EUR / CPI_poland * 100,
      country == "CZ" ~ sales_EUR / CPI_czech * 100,
      TRUE ~ sales_EUR / CPI_euro * 100
    ))
  ) |>
  # Odstránenie nepotrebných stĺpcov
  select(-sales, -CZK, -PLN, -CPI_poland, -CPI_czech, -CPI_euro)


# Konverzia na tsibble pre časovú analýzu
data_cleaned <- data_cleaned |>
  as_tsibble(
    key = c(country, division, channel, product_group),
    index = date
  )

Vizualizácia trendov predaja

Vizualizácia nám pomáha pochopiť, ako sa predaje menili v čase, identifikovať trendy, sezónnosť a možné anomálie. Hoci sa môže zdať, že jednoduché nakreslenie časovej krivky je „amatérsky“ alebo nie príliš sofistikovaný prístup, v skutočnosti ide o jednu z najdôležitejších a najúčinnejších metód na pochopenie dát. Grafická analýza často odhalí vzory, ktoré by inak zostali skryté v číselných agregátoch alebo štatistických modeloch. Dobre zvolená vizualizácia dokáže rýchlo upozorniť na kľúčové momenty, ako sú prudké poklesy alebo nárasty predajov, sezónne výkyvy či štrukturálne zlomy, a pomáha formovať ďalšie analytické kroky.

Kód
ggplot(data_cleaned |> filter(year(date) >= 2022), aes(x = date, y = sales_EUR, color = product_group)) +
  geom_line() +
  facet_wrap(division ~ country ~ channel, scales = "free",
             ncol = 2) +
  labs(
    title = "Predajné trendy po krajine, divízii a predajnom kanáli",
    x = "Dátum",
    y = "Predaj (EUR)"
  ) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE))

Pozorovania:

  • V rôznych krajinách a kanáloch predaja môžu byť rôzne trendy.
  • V ČR môže byť vidieť určitý pokles, zatiaľ čo v Poľsku rast.
  • Predaje v kamenných predajniach (ak máme takýto kanál) môžu byť stabilné, ale nižšie ako v online.
  • Potenciálnu sezónnosť (napr. pred Vianocami) je vhodné ďalej preskúmať.

Pre forecasty a prípadné vytváranie hierarchických časových radov je užitočné dáta sumarizovať na rôznych úrovniach. K tomu nám slúži funkcia aggregate_key(). Takto získame napr. sumu predajov (EUR) a očistených predajov (EUR_CPI_adj) pre rôzne úrovne hierarchie (krajina, divízia, kanál, produkt).

Kód
data_cleaned_agg <- data_cleaned |>
  aggregate_key(
    (country / division / channel) * product_group,
    sales_EUR = sum(sales_EUR),
    sales_EUR_CPI_adj = sum(sales_EUR_CPI_adj)
  )

Vizualizácia adjustovaných predajov a stabilizácia rozptylu

Porovnanie pôvodných predajov a CPI-očistených

Najprv si zistíme maximálnu hodnotu predajov v zvolenej podskupine, aby sme zachovali rovnakú mierku na grafoch.

Kód
max_sales_EUR <- data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    product_group %in% c("PCs", "Notebooks", "Software")
  ) |>
  slice_max(order_by = sales_EUR, n = 1) |>
  pull(sales_EUR)

data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    product_group %in% c("PCs", "Notebooks", "Software")
  ) |>
  autoplot(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE),
                     limits = c(0, max_sales_EUR)) +
  labs(
    x = "Dátum",
    y = "Predaj (EUR)",
    title = "Pôvodné predaje"
  )

Kód

data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    product_group %in% c("PCs", "Notebooks", "Software")
  ) |>
  autoplot(sales_EUR_CPI_adj) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE),
                     limits = c(0, max_sales_EUR)) +
  labs(
    x = "Dátum",
    y = "Predaj (EUR, CPI Adj.)",
    title = "CPI adjustované predaje"
  )

Z porovnania grafov je zrejmé, že rast predaja notebookov je pred úpravou príliš optimistický a do značnej miery sú vyššie predaje dôsledkom inflácie.

Stabilizácia rozptylu (log transformácia)

Pri časových radoch, ktoré majú rastúci trend alebo veľké rozdiely v hodnotách, môže logaritmická transformácia pomôcť stabilizovať rozptyl.

Kód

# Pred log-transformáciou
data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    product_group == "Notebooks"
  ) |>
  autoplot(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE)) +
  labs(
    x = "Dátum",
    y = "Predaj (EUR)"
  )

Kód

# Po log-transformácii
data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    product_group == "Notebooks"
  ) |>
  autoplot(log(sales_EUR)) +
  labs(
    x = "Dátum",
    y = "Predaj (EUR, log-trans.)"
  )

Použitie logaritmickej transformácie má niekoľko výhod. Najčastejšie sa používa za účelom:

  • Odstránenia efektu rastúcich sezónnych výkyvov (multiplikatívna sezónnosť) – tento jav nastáva, keď sú sezónne výkyvy závislé od úrovne samotného časového radu – čím vyššia je hodnota radu, tým väčšie sú absolútne sezónne fluktuácie.
  • Zlepšuje stacionaritu – redukuje rastúci trend a stabilizuje rozptyl, čo je dôležité pre modely ako ARIMA, ktoré vyžadujú stacionárne dáta.
  • Mení interpretáciu – rozdiely v logaritmovanom rade odpovedajú percentuálnym zmenám v pôvodnom rade.

Ak po logaritmickej transformácii sezónnosť stále nie je aditívna, ďalším krokom môže byť diferenciácia.

Sezónnosť a dekompozícia časových radov

Teraz si ukážeme, ako rozložiť (dekomponovať) časovú radu na trend, sezónnu a reziduálnu (náhodnú) zložku pomocou metódy STL (Seasonal and Trend decomposition using Loess). Používa LOESS (Local Regression Smoothing) na vyhladenie trendu a sezónnosti.

STL má oproti iným metódam (napr. klasická dekompozícia alebo X-13-ARIMA-SEATS) výhody ako:

  • Flexibilná sezónnosť – umožňuje zmenu sezónnych vzorcov v čase
  • Robustnosť voči outlierom – lepšie zvláda extrémne hodnoty
  • Možnosť nastaviť parametre trendu a sezónnosti (dĺžku časového okna) – umožňuje jemnejšiu kontrolu nad výsledkami

V našom príklade použijeme parametre:

  • trend(window = 21) – trendová zložka sa vyhladzuje pomocou LOESS s oknom 21 období (ide o mesačné dáta, trend sa teda vypočítava na 21-mesačnej perióde). Väčšie okno znamená hladšiu krivku trendu.
  • season(window = “periodic”) – sezónnosť sa modeluje ako plne periodická, čo znamená, že metóda využije všetky dostupné údaje na určenie sezónnych vzorcov.

STL sa používa napr pri detektcii odľahlých hodnôt alebo keď potrebujeme očistiť časový rad od sezónnosti (a trendu) pred ďalšou analýzou (napr. forecasting modely založené na ML).

Kód

dcmp <- data_cleaned_agg |>
  filter(
    country == "SK",
    channel == "ONLINE",
    product_group == "PCs"
  ) |>
  model(
    stl = STL(sales_EUR ~ trend(window = 21) + season(window = "periodic"))
  )

components(dcmp) |>
  autoplot() +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE)) +
  labs(x = "Dátum")

Zároveň si môžeme zistiť štatistické vlastnosti (features) časových radov a pozrieť, ktoré série majú najsilnejší alebo najslabší trend či sezónnosť.

Popis jednotlivých STL Features (z funkcie feat_stl()):

  • trend_strength – Udáva, aký veľký podiel variability v časovom rade vysvetľuje trendová zložka. Hodnota sa pohybuje medzi 0 a 1 – vyššie hodnoty znamenajú silný trend. Ak sa hodnota blíži k 1, dáta majú výrazný dlhodobý trend. Ak sa hodnota blíži k 0, trend je minimálny.
  • seasonal_strength – Udáva, aký veľký podiel variability vysvetľuje sezónna zložka. Hodnota sa pohybuje medzi 0 a 1 – čím vyššia hodnota, tým výraznejšia sezónnosť. Ak sa blíži k 0, časový rad nemá sezónne vzory.
  • spikiness – Meria krátkodobú volatilitu v zvyškovej (reziduálnej) zložke časového radu. Vyššie hodnoty znamenajú výraznejšie neočakávané výkyvy, ktoré nie sú vysvetlené trendom ani sezónnosťou. Používa sa na identifikáciu prítomnosti anomálií alebo šokov v dátach.
  • peak – Identifikuje, v ktorom čase v rámci sezónneho cyklu nastáva najvyšší bod sezónnosti. Napríklad, v prípade mesačných dát, peak = 6 znamená, že predaje sú najvyššie v Júni.
  • trough – Identifikuje, v ktorom čase v rámci sezónneho cyklu nastáva najnižší bod sezónnosti. Napríklad, v prípade mesačných dát, trough = 1, znamená, že predaje sú najnižšie v Januári.
  • linearity – Udáva, ako lineárny je trend časového radu. Vyššie hodnoty znamenajú silnejšiu lineárnu zložku trendu (stály rast alebo pokles). Hodnota blížiaca sa k 0 znamená, že trend nie je výrazne lineárny, ale môže byť cyklický alebo stacionárny.
  • curvature – Meria zakrivenie trendu – teda ako veľmi sa mení jeho sklon. Vyššie hodnoty znamenajú nelineárne trendy (napr. zrýchľujúci rast alebo spomalenie poklesu). Ak sa hodnota blíži k 0, trend je takmer priamka.
  • stl_e_acf1 – Prvá autokorelácia reziduálov (zvyškov časového radu). Meria, do akej miery sú dnešné odchýlky od trendu a sezónnosti závislé od predchádzajúcich hodnôt. Ak sa hodnota blíži k 1, znamená to silnú časovú závislosť v reziduálnej zložke.
  • stl_e_acf10 – Súčet štvorcov prvých desiatich autokorelácií reziduálnej zložky. Namiesto jednej hodnoty autokorelácie (ako pri stl_e_acf1) táto metrika sumarizuje celkovú autokorelačnú štruktúru reziduálov do oneskorenia (lag) 10.

Všetky tieto metriky majú svoje praktické využitie napr. pri výbere vhodného modelu, detekcii prítomnosti anomálií, interpretácii sezónnych vzorov. Nízke hodnoty stl_e_acf1 a stl_e_acf10 ukazujú, že reziduá sú takmer náhodné a STL dobre rozdelila časový rad na trend a sezónnosť. Naopak, ak sú vysoké, V reziduálnej zložke ostáva autokorelačná štruktúra – môže ísť o nezachytený trend alebo cyklus. Vtedy môže byť potrebné lepšie nastaviť trendové/sezónne okno v STL, napr. experimentovať s rôznymi hodnotami trend(window = X) a season(window = Y).

Kód

stl_features <- data_cleaned |>
  features(sales_EUR, feat_stl)

stl_features
#> # A tibble: 54 × 13
#>    country division channel product_group trend_strength seasonal_strength_year
#>    <chr>   <chr>    <chr>   <chr>                  <dbl>                  <dbl>
#>  1 CZ      Retail   ONLINE  Accessories            0.906                  0.755
#>  2 CZ      Retail   ONLINE  Components             0.952                  0.502
#>  3 CZ      Retail   ONLINE  Monitors               0.968                  0.645
#>  4 CZ      Retail   ONLINE  Notebooks              0.981                  0.674
#>  5 CZ      Retail   ONLINE  PCs                    0.908                  0.754
#>  6 CZ      Retail   ONLINE  Software               0.287                  0.647
#>  7 CZ      Retail   SHOPS   Accessories            0.655                  0.678
#>  8 CZ      Retail   SHOPS   Components             0.535                  0.388
#>  9 CZ      Retail   SHOPS   Monitors               0.733                  0.559
#> 10 CZ      Retail   SHOPS   Notebooks              0.826                  0.416
#> # ℹ 44 more rows
#> # ℹ 7 more variables: seasonal_peak_year <dbl>, seasonal_trough_year <dbl>,
#> #   spikiness <dbl>, linearity <dbl>, curvature <dbl>, stl_e_acf1 <dbl>,
#> #   stl_e_acf10 <dbl>

Trend a sezónnosť

Trend

Nižšie ilustrujeme, ako nájsť a zobraziť sériu s minimálnou a maximálnou silou trendu.

Skúmanie autokorelačných vzorcov:

Kód

# Minimálna a maximálna sila trendu
trend_strength_min <- stl_features |>
  filter(trend_strength == min(trend_strength))

trend_strength_max <- stl_features |>
  filter(trend_strength == max(trend_strength))

# Príklad zobrazenia série s minimálnou silou trendu
data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    product_group == "Software"
  ) |>
  autoplot(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE), limits = c(0, 80000)) +
  labs(
    title = "Časový rad s najslabším trendom",
    x = "Dátum",
    y = "Predaj (EUR)"
  )

Kód

# Príklad zobrazenia série s maximálnou silou trendu
data_cleaned_agg |>
  filter(
    country == "PL",
    channel == "ONLINE",
    product_group == "Monitors"
  ) |>
  autoplot(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE), limits = c(0, 80000)) +
  labs(
    title = "Časový rad s najsilnejším trendom",
    x = "Dátum",
    y = "Predaj (EUR)"
  )

Sezónnosť

Rovnako postupujeme pri sezónnosti

Kód

# Minimálna a maximálna sezónnosť
season_strength_min <- stl_features |>
  filter(seasonal_strength_year == min(seasonal_strength_year))

season_strength_max <- stl_features |>
  filter(seasonal_strength_year == max(seasonal_strength_year))

# Zobrazenie série s minimálnou sezónnosťou
data_cleaned_agg |>
  filter(
    country == "SK",
    channel == "B2B",
    product_group == "Components"
  ) |>
  autoplot(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE), limits = c(0, 200000)) +
  labs(
    title = "Časový rad s najslabšou sezónnosťou",
    x = "Dátum",
    y = "Predaj (EUR)"
  )

Kód

# Zobrazenie série s maximálnou sezónnosťou
data_cleaned_agg |>
  filter(
    country == "SK",
    channel == "ONLINE",
    product_group == "PCs"
  ) |>
  autoplot(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE), limits = c(0, 200000)) +
  labs(
    title = "Časový rad s najsilnejšou sezónnosťou",
    x = "Dátum",
    y = "Predaj (EUR)"
  )

Knižnice fable a feasts umožňujú rýchlo vytvárať sezónne grafy (gg_season()) a sub-série (gg_subseries()).

Funkcia gg_season() umožňuje vizualizovať sezónnosť v časovom rade tým, že zobrazuje jednotlivé sezónne cykly na jednom grafe. To znamená, že dáta sú rozdelené podľa sezónneho obdobia (napr. mesiace v roku, dni v týždni) a zobrazené pre všetky dostupné roky, čo uľahčuje porovnanie sezónnych trendov naprieč rôznymi obdobiami.

Interpretácia:

  • Každá čiara predstavuje jeden rok, pričom osi X zobrazujú sezónne obdobie (jednotlivé mesiace).
  • Umožňuje vidieť opakovateľné vzory – napr. kedy majú predaje tendenciu rásť alebo klesať.
  • Ak sú všetky roky veľmi podobné, znamená to stabilnú sezónnosť.
  • Ak sú medzi jednotlivými rokmi veľké rozdiely, sezónnosť môže byť nestabilná alebo meniaca sa v čase.
Kód

# Retail - Online
data_cleaned_agg |>
  filter(
    is_aggregated(product_group),
    country == "CZ",
    division == "Retail",
    channel == "ONLINE"
  ) |>
  gg_season(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE)) +
  labs(
    x = "Mesiac",
    y = "Predaj (EUR)",
    title = "Sezónnosť predajov v divízii Retail - Online Predaje (CZ)"
  )

Kód

# B2B
data_cleaned_agg |>
  filter(
    is_aggregated(product_group),
    country == "CZ",
    channel == "B2B"
  ) |>
  gg_season(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE)) +
  labs(
    x = "Mesiac",
    y = "Predaj (EUR)",
    title = "Sezónnosť predajov v divízii B2B (CZ)"
  )

Funkcia gg_subseries() rozkladá časový rad na jednotlivé sezónne obdobia, pričom každý sezónny cyklus je znázornený ako samostatná séria. Toto je užitočné na podrobnejšiu analýzu sezónnych vzorov, pretože umožňuje zistiť, či sezónnosť ostáva konzistentná alebo sa v priebehu času mení.

Interpretácia:

  • Na osi X sú sezónne obdobia (napr. mesiace v roku).
  • Každý box predstavuje priemernú hodnotu predaja pre dané obdobie v rôznych rokoch.
  • Sub-sériové grafy umožňujú lepšie pochopiť, ako sa sezónnosť vyvíja v priebehu času.
  • Ak niektoré mesiace vykazujú veľké výkyvy medzi rokmi, sezónne efekty sa môžu meniť a treba ich modelovať dynamicky.
Kód

data_cleaned_agg |>
  filter(
    country == "CZ",
    channel == "ONLINE",
    is_aggregated(product_group)
  ) |>
  gg_subseries(sales_EUR) +
  scale_y_continuous(labels = function(x) format(x, big.mark = " ", scientific = FALSE)) +
  labs(
    x = "Mesiac",
    y = "Predaj (EUR)",
    title = "Subseries graf pre Retail - Online predaje (CZ)"
  )

Autokorelácia

Autokorelácia odhaľuje, či (a do akej miery) závisia hodnoty v čase od svojich predchádzajúcich hodnôt. Inými slovami, skúma vzťah medzi hodnotami časového radu v rôznych časových bodoch a pomáha identifikovať vzorovosť, cykly a dlhodobé vzťahy v dátach.

Autokorelácia pri oneskorení (lag) k sa vypočíta ako Pearsonov korelačný koeficient medzi pôvodným časovým radom a jeho posunutou hodnotou. Ak má vysoké hodnoty (pozitívne alebo negatívne), naznačuje trend alebo systematický vzor v dátach. Ak sa autokorelácia blíži k nule časový rad nemá vzorovú štruktúru a správa sa ako šum (random noise). Hodnoty autokorelácie pomáhajú detekovať trendy a sezónne vzory v časových radoch, sú základným vstupom pri výbere správneho štatistického modelu a umožňujú diagnostikovať modely – reziduá dobrého modelu by mali mať nízku autokoreláciu.

Okrem ACF (autocorrelation function) je dôležitým ukazovateľom aj PACF (partial autocorrelation function), ktorý meria koreláciu medzi hodnotou a jej lagovaných hodnôt po odstránení efektu ostatných lagovaných hodnôt. Používa sa pri výbere autoregresívnych (AR) modelov v ARIMA rodine modelov.

Kód
# Autocorrelation Function (ACF)
data_cleaned |>
  filter(
    country == "SK",
    channel == "ONLINE",
    product_group == "PCs"
  ) |>
  ACF(sales_EUR) |>
  autoplot()

Kód

# Partial Autocorrelation Function (PACF)
data_cleaned |>
  filter(
    country == "SK",
    channel == "ONLINE",
    product_group == "PCs"
  ) |>
  PACF(sales_EUR) |>
  autoplot()

Diferencovanie

Diferencovanie je technika používaná na odstránenie trendovej a sezónnej zložky z časového radu. Je dôležité najmä pri modeloch ako ARIMA, ktoré vyžadujú stacionárne dáta (t.j. bez systematického rastu alebo poklesu v čase). Diferencovanie nahrádza pôvodné hodnoty časového radu rozdielom medzi hodnotou v čase t a t-1. Ak existuje sezónna zložka, môžeme použiť sezónne diferencovanie, kde sa odpočítava hodnota z predchádzajúceho sezónneho obdobia (napr. pri mesačných dátach odpočítavame hodnotu spred 12 mesiacov).

Kód

data_diff <- data_cleaned |>
  filter(
    country == "SK",
    channel == "ONLINE",
    product_group == "PCs"
  ) |>
  mutate(diff_sales = difference(sales_EUR))

data_diff |>
  autoplot(diff_sales) +
  labs(
    x = "Dátum",
    y = "Diferencované predaje (EUR)"
  )

Či bolo diferencovanie úspešné zistíme pomocou vizualizácie diferenciovaného radu, aplikovaním ACF (ak je diferencovaný rad stacionárny, ACF by mala rýchlo klesať na nulu) alebo pomocou Dickey-Fullerovho testu stacionarity.

Detekcia anomálií

Anomália je bod alebo skupina bodov, ktoré nejakým spôsobom nezapadajú do normálneho alebo očakávaného rozsahu hodnôt. Nie každá anomália je však nežiaduca. Hoci niektoré vznikajú napríklad v dôsledku chýb v meraní, iné môžu byť výsledkom špecifickej situácie v procese, ktorá môže mať vysokú výpovednú hodnotu. V literatúre aj praxi sa preto používajú rôzne označenia pre anomálie, napríklad outliers (odľahlé hodnoty), novelties, či noise (šum). Podľa kontextu sa odlišuje aj spôsob práce s anomáliami. Ak ide o chyby, najlepším riešením je tieto hodnoty odstrániť (napr. nahradením). Ak však predstavujú dôsledok dôležitých udalostí (napr. zmena správania, zlyhanie zariadenia a pod.), môžu slúžiť ako základ pre ďalšiu analýzu.

V prípade časových radov je situácia ešte zložitejšia, pretože v niektorých prípadoch nie je anomália definovaná iba svojou hodnotou, ale aj zmenou vo vzorci (časovaní). Príkladom môže byť EKG pacienta s arytmiou – v tomto prípade je anomália definovaná nepravidelnosťou medzi údermi srdca, nie samotnou hodnotou elektrickej aktivácie.

Existuje viacero prístupov a množstvo odborných článkov venujúcich sa detekcii anomálií. Medzi základné metódy patria:

  • IQR (Interquartile Range) – Anomálie sú definované ako hodnoty ležiace mimo interkvartilného rozpätia, typicky 1,5×IQR od prvého (Q1) a tretieho (Q3) kvartilu.
  • GESD (Generalized Extreme Studentized Deviate Test) – Iteratívna metóda identifikácie odľahlých hodnôt na základe štatistických testov.
  • Pokročilé metódy – Napríklad Twitter/STS (Seasonal-Trend Decomposition), algoritmy strojového učenia ako Isolation Forest, DBSCAN a ďalšie. Tieto metódy však presahujú rámec tohto blogu.

Viac informácií môžete nájsť napr. v tomto článku.

V nasledujúcom príklade použijeme STL dekompozíciu v kombinácii s metódou IQR. Funkcia time_decompose() rozloží časovú radu na trend, sezónnosť a zvyšky (remainders). Následne anomalize() detekuje anomálie práve vo zvyškoch a time_recompose() umožní opätovné zloženie časovej rady.

Kód

ts_anomalize <- data_cleaned_agg |>
  as_tibble() |> 
  mutate(date = as.Date(date)) |> 
  filter(country == "SK", channel == "ONLINE", product_group == "PCs") |>
  time_decompose(sales_EUR, method = "stl") |>
  anomalize(remainder, method = "iqr", alpha = 0.1) |>
  time_recompose()

plot_anomalies(ts_anomalize)

Záver

V tomto blogu sme prešli základný proces exploratívnej analýzy časových radov (EDA) s dôrazom na čistenie, transformáciu, vizualizáciu a detekciu anomálií. Hlavné kroky zahŕňali:

  • Načítanie a kontrolu dát – overenie úplnosti, pravidelnosti a príprava údajov na analýzu.
  • Čistenie a transformáciu – očistenie predajov o infláciu, konverzia do jednotnej meny a stabilizácia rozptylu.
  • Vizualizáciu – analýzu trendov, sezónnosti a identifikáciu vzorov v predajoch.
  • Dekompozíciu časových radov (STL) – rozklad série na trendovú, sezónnu a reziduálnu zložku.
  • Autokoreláciu (ACF, PACF) – skúmanie časových vzťahov a závislostí v dátach.
  • Diferencovanie – odstránenie trendu a sezónnosti pre získanie stacionárnych časových radov.
  • Detekciu anomálií – identifikáciu neobvyklých bodov pomocou IQR a STL dekompozície.

Tieto postupy sú kľúčové pri analýze časových radov a nachádzajú široké uplatnenie v mnohých odvetviach a vedných odboroch. Pomáhajú lepšie porozumieť historickým trendom, predikovať budúci vývoj a identifikovať nečakané výkyvy v dátach.

V ďalšej časti sa zameriame na clustrovanie časových radov, kde budeme segmentovať rôzne časové rady na základe ich priebehu alebo štatistických charakteristík. Následne sa budeme venovať forecastovaniu: ukážeme využitie tradičných metód (ARIMA, ETS) a zároveň predstavíme možnosti strojového učenia (napr. gradient boosting). Porovnáme, v čom sa tieto prístupy odlišujú a na aké situácie sú vhodné.

Referencie

Viac informácií o spomínaných metódach nájdete v:

  • Hyndman, R.J., & Athanasopoulos, G. (2021) Forecasting: principles and practice, 3rd edition, OTexts: Melbourne, Australia. OTexts.com/fpp3
  • Boniol, Paul & Liu, Qinghua & Huang, Mingyi & Palpanas, Themis & Paparrizos, John. (2024). Dive into Time-Series Anomaly Detection: A Decade Review. 10.48550/arXiv.2412.20512
  • Dokumentácia ku knižniciam: tsibble, fable, feasts, anomalize a timetk.

susR: Zjednodušenie práce s dátami Štatistického úradu SR v R 150 150 cleandata

susR: Zjednodušenie práce s dátami Štatistického úradu SR v R

V tomto blogu vám predstavím knižnicu susR, ktorá umožňuje jednoduché pripojenie k API Štatistického úradu SR priamo z R. Ukážem, ako zefektívniť analýzu štatistických údajov, vrátane ukážok kódu a plánov na rozšírenie funkcionality knižnice.

blog

V dnešnej dobe je prístup k otvoreným dátam kľúčový pre výskum, analýzy a tvorbu rozhodovacích nástrojov. Z tohto dôvodu som vytvoril knižnicu susR, ktorá umožňuje jednoduché pripojenie k API Štatistického úradu Slovenskej republiky (ŠÚ SR) priamo z prostredia R. Zjednodušuje prácu s oficiálnymi štatistickými údajmi, čím uľahčuje analýzu, vizualizáciu a reporting.

Prečo je susR užitočný?

Ak pracujete s oficiálnymi štatistickými údajmi, určite viete, aké dôležité je mať aktuálne a presné údaje. susR Vám umožňuje pripojiť sa priamo k zdroju dát – API ŠÚ SR, čo Vám poskytuje:

  • Reprodukovateľnosť: Celý proces stiahnutia a spracovania dát je automatizovaný, čím zabezpečíte, že Váš analýzny “pipeline” bude reprodukovateľný.
  • Flexibilitu: Vďaka možnosti filtrovať tabuľky a vyberať konkrétne dimenzie si môžete presne definovať, aké údaje potrebujete pre Vašu analýzu.
  • Efektivitu: Nemusíte strácať čas ručným získavaním a transformáciou dát. Funkcie to spravia za Vás, pričom sa môžete sústrediť na analýzu a vizualizáciu výsledkov.

Čo dokáže knižnica susR?

susR prináša rad funkcií, ktoré Vám umožnia:

  • Zobraziť dostupné tabuľky: Pomocou funkcie susr_tables(), ktorej názov jasne hovorí, môžete získať zoznam všetkých dostupných datasetov (tabuliek) poskytovaných ŠÚ SR. Tento zoznam obsahuje kódy tabuliek, popisy a informácie o dimenziách, čo výrazne uľahčuje výber správnych dát.
  • Získavať informácie o dimenziách a ich hodnotách: Knižnica umožňuje zistiť, aké dimenzie má zvolená tabuľka (napríklad roky, regióny, indikátory) a aké možnosti výberu sú dostupné pomocou funkcie susr_dimension_values(). To je veľmi dôležité najmä v prípade, keď je potrebné vytvoriť vlastnú selekciu z veľkého objemu dát.
  • Sťahovať dáta: Hlavná funkcia knižnice fetch_susr_data() umožňuje vytvoriť požiadavku na API s vlastnými výberovými parametrami. Vďaka tomu sa údaje z API automaticky načítajú a transformujú do podoby “tibbles”, ktoré sú pripravené na analýzu priamo v R.
  • Jednoduché filtrovanie: Môžete filtrovať tabuľky podľa domény, subdomény (ich zoznam aj s kódmi tabuliek získate pomocou funkcie susr_domains()) alebo priamo podľa kódu tabuľky. Týmto spôsobom si môžete rýchlo zúžiť výsledný zoznam podľa vlastných potrieb.

Príklad: Predstavme si, že máte záujem analyzovať dáta o priemernom veku a populácii okresov.

Pomocou susr_domains() si pozrieme zoznam tabuliek v subdoméne “Population and migration” a vyberieme tabuľky, ktoré obsahujú potrebné údaje. Následne zistíme pomocou funkcie susr_tables() aké parametre tabulky majú a aké hodnoty sa dajú zvoliť. Pre potreby tejto analýzi sú to:

Tabuľka om7013rr, ktorá obsahuje údaje o strednom stave obyvateľstva a má nasledujúce parametre:

om7013rr_vuc: kódy regiónov om7013rr_obd: roky om7013rr_ukaz: ukazovatele om7013rr_poh: pohlavie

Tabuľka om7005rr, ktorá obsahuje údaje o vekovom zložení obyvateľstva a má nasledujúce parametre:

om7005rr_vuc: kódy regiónov om7005rr_obd: roky om7005rr_ukaz: ukazovatele om7005rr_poh: pohlavie

Pomocou susR si môžete jednoducho postaviť svoju požiadavku, stiahnuť a spracovať dáta do tabuľky napr. takýmto workflowom:

Kód
# namiesto vypisovania kódov okresov využijeme vektor v R, ktorý použijeme ako parameter
districts <- susr_dimension_values("om7013rr",
                                   "om7013rr_vuc") |> 
  filter(str_detect(element_label, "District of"))


params <- list(
  "om7013rr", # tabuľka so stredným stavom
  list( 
    districts$element_value, # okresy
    "all", # roky              
    "IN010052", # kód pre stredný stav               
    c("1", "2") # pohlavie (1 = muži, 2 = ženy)                
    
    ),
  "om7005rr", # tabuľka so priemerným vekom
  list( 
    districts$element_value, # okresy
    "all", # roky                  
    "IN010089", # kód pre priemerný vek        
    c("1", "2") # pohlavie (1 = muži, 2 = ženy)           
    )
)

res <- fetch_susr_data(params) # volanie API

# res je vnorený list, v ktorom sú výsledky API volania
pop_df <- res[["om7013rr"]]
age_df <- res[["om7005rr"]]

Plány do budúcnosti

Do budúcnosti plánujem rozšíriť funkcionalitu knižnice susR o niekoľko vylepšení:

Rozšírené spracovanie dimenzií:

  • Chcem pridať funkcie, ktoré umožnia používateľovi zadávať výbery vo forme intervalov (napríklad last5, 2010:, :2015), alebo zadávať výbery na základe obsahu – napr. zadať „districts“, „regions“, alebo „municipalities“. Možno implementovať aj funkciu contains() pre vyhľadávanie (napr. contains(“Brezno”) pre výber obce brezno).
  • Integrácia s giscoR: Plánujem vytvoriť wrapper pre giscoR, ktorý by pomohol geokódovať a pripojiť geografické informácie k dátam zo ŠÚ SR, čo by umožnilo vizualizácie na mape a geodátové analýzy.
  • Viac vignett: Chcem pridať ďalšie podrobné príklady použitia knižnice – pokročilejšie scenáre, v ktorých budú ukázané rôzne aspekty analýz a spracovania dát.
  • Publikovanie na CRAN: Po doladení a získavaní spätnej väzby od používateľov plánujem balíček publikovať na CRAN, čo zjednoduší jeho inštaláciu a používanie pre širšiu komunitu.

Ako vytvoriť interaktívny dashboard v R pomocou Quarto 150 150 cleandata

Ako vytvoriť interaktívny dashboard v R pomocou Quarto

V tomto blogu vám predstavím Quarto ako moderný nástroj na tvorbu interaktívnych dashboardov. Porovnám ho s alternatívami ako Shiny, Power BI a Tableau, ukážem jeho výhody, obmedzenia a možnosti prispôsobenia pomocou HTML, CSS a JavaScript. Ak hľadáte efektívny spôsob, ako prezentovať svoje dáta, tento blog je pre vás.

interactive_dashboard_quarto

Ak ste čítali niektoré z mojich predchádzajúcich článkov, napríklad Vývoj Shiny aplikácie na optimalizáciu trás alebo Vývoj a nasadenie Shiny aplikácií v jazyku R, viete, že Shiny je jedným z najpopulárnejších nástrojov na tvorbu interaktívnych aplikácií v R.

Aj keď je Shiny veľmi výkonný, jeho učiaca krivka môže byť strmá a nasadzovanie aplikácií vyžaduje server. Preto, ak nepotrebujete príliš komplexné riešenia, stojí za to zvážiť Quarto, ktoré ponúka jednoduchší spôsob tvorby interaktívnych dashboardov priamo v prehliadači.

Čo je Quarto?

Quarto je moderný nástroj na tvorbu reportov, dokumentov, a dashboardov priamo v R. Umožňuje kombinovať text, kód a interaktívne prvky do jedného elegantného výstupu. V porovnaní so Shiny je zdieľanie a nasadzovanie výrazne jednoduchšie, najmä cez služby ako GitHub Pages.

Quarto je v podstate nástupcom RMarkdown. Ak ste už v minulosti pracovali s RMarkdown, Quarto vám bude veľmi známe. Ponúka však širší záber – umožňuje nielen vytváranie reportov a dokumentov, ale aj plne interaktívnych dashboardov, webových stránok, či rôznych formátov prezentácií. Quarto prináša väčšiu flexibilitu a rozšírenú podporu rôznych programovacích jazykov, ako sú R, Python, Julia a ďalšie, čím sa stáva univerzálnejším nástrojom pre moderné dátové analýzy a vizualizácie.

Jednou z veľkých výhod Quarto je podpora HTML, CSS a JavaScript, vďaka čomu máte veľkú flexibilitu v prispôsobovaní dizajnu a funkcií svojho dashboardu. To umožňuje vytvárať profesionálne riešenia, ktoré presne zodpovedajú vašim potrebám.

Vytváranie interaktívnych prvkov v Quarto

Aj keď Quarto podporuje hlavne statické dashboardy, existujú spôsoby, ako do nich pridať interaktivitu:

1. Runtime: Shiny

Ak je potrebná pokročilá interaktivita, Quarto umožňuje používať runtime: shiny, čo znamená, že všetky výhody Shiny aplikácií môžete integrovať priamo do Quarto dashboardu. Avšak nasadzovanie si vyžaduje server, čo môže byť pre niektorých používateľov obmedzujúce.

2. Crosstalk – Jednoduchá interaktivita

Pre menej náročné prípady môžete využiť knižnicu Crosstalk. Tá umožňuje synchronizáciu interaktívnych komponentov, ako napríklad:

  • DT: dynamické tabuľky
  • Plotly: interaktívne grafy
  • Leaflet: mapové vizualizácie

Jednou z hlavných výhod je, že Crosstalk a knižnice, ako summarywidget fungujú priamo v prehliadači pomocou JavaScriptu, čo znamená, že zmeny vo filtroch a interakciách sú extrémne rýchle. Všetko sa vykresľuje priamo na strane klienta (v prehliadači), takže nie je potrebné odosielať dáta na server. To zaručuje plynulé a responzívne ovládanie.

Deployment je navyše jednoduchý, pretože nevyžaduje server. Stačí dashboard publikovať, napríklad cez GitHub Pages, čím sa výrazne zjednoduší jeho zdieľanie.

KPI karty a knižnica summarywidget

Ak potrebujete do dashboardu zahrnúť KPI karty (tzv. valueboxy), Crosstalk vás v tomto smere obmedzuje. Pre tento účel odporúčam knižnicu summarywidget, ktorá umožňuje zobrazovať základné štatistiky v prehľadnej forme.

Zistil som však, že pôvodná knižnica summarywidget má obmedzenú funkcionalitu, preto som ju upravil a rozšíril o viac možností formátovania a štatistík. Upravenú verziu si môžete nainštalovať pomocou:

devtools::install_github("Arnold-Kakas/summarywidget")

Rovnako ako Crosstalk, aj summarywidget využíva JavaScript, čo zaručuje veľmi rýchle vykresľovanie a responzívnosť priamo v prehliadači.

Porovnanie: Quarto vs. Shiny

Funkcia Quarto Shiny
Rýchlosť vykresľovania Pri jednoduchých interakciách (Crosstalk, Plotly) veľmi rýchle, pri runtime: shiny porovnateľné so Shiny. Pri všetkých interakciách sa spolieha na server, môže byť pomalšie pri veľkej záťaži.
Možnosti formátovania Flexibilné – umožňuje použitie JS, CSS a HTML. Flexibilné – umožňuje použitie JS, CSS a HTML.
Nasadzovanie a zdieľanie Možnosť nasadiť ako statickú stránku (bez servera) alebo interaktívnu aplikáciu cez runtime: shiny, ktorá vyžaduje server. Vyžaduje server (napr. Shiny Server, RStudio Connect, AWS, GCP…) pre interaktivitu a zdieľanie.
Interaktivita Interaktivita pomocou Crosstalk (plotly, DT, leaflet) alebo OJS. Pri runtime: shiny plne podporuje Shiny interaktivitu. Bohatá podpora interaktivity s plným využitím serverovej logiky a reaktívnych komponentov.
Podpora pre komplexné prepojenia Obmedzené na možnosti Shiny v prípade runtime: shiny, pri Crosstalk obmedzené len na synchronizáciu filtrov. Veľmi silná – umožňuje zložité interakcie a prepojenia medzi komponentmi prostredníctvom reaktivity.
Cena Bezplatné (open-source). Bezplatné (open-source), ale prevádzka na serveroch môže byť nákladná.

Hlavné výhody Quarto:

  • Jednoduché zdieľanie: Deployment je jednoduchý. Stačí publikovať dashboard, napríklad cez GitHub Pages.
  • Rýchlosť a responzívnosť: Vďaka využívaniu JavaScriptu sú zmeny vo filtroch a interakciách extrémne rýchle, pretože všetko beží na strane klienta (v prehliadači).
  • Nízka zložitosť: Na rozdiel od Shiny, nepotrebujete server, ak využívate Crosstalk.

Obmedzenia:

  • Obmedzená interaktivita: Quarto nemá také široké možnosti interakcie ako Shiny.
  • Menej rozvinutý ekosystém: Niektoré knižnice (napríklad summarywidget) si vyžadujú úpravy na mieru.

Porovnanie: Quarto vs. Power BI

Funkcia Quarto Power BI
Rýchlosť vykresľovania Pri jednoduchých interakciách (Crosstalk, Plotly) veľmi rýchle, pri runtime: shiny porovnateľné so Shiny. Môže byť pomalšie pri práci s veľkými datasetmi, najmä pri komplexných vizualizáciách alebo DAX metrikách.
Možnosti formátovania Veľké možnosti prispôsobenia pomocou CSS a HTML. Obmedzené na rozhranie Power BI, úpravy formátovania sú menej flexibilné.
Nasadzovanie a zdieľanie Možnosť nasadiť ako statickú stránku (bez servera) alebo interaktívnu aplikáciu cez runtime: shiny, ktorá vyžaduje server. Nasadzovanie vyžaduje Power BI službu.
Interaktivita Interaktivita pomocou Crosstalk (plotly, DT, leaflet) alebo OJS. Pri runtime: shiny plne podporuje Shiny interaktivitu. Široká podpora interaktivity a natívnych vizualizácií.
Podpora pre komplexné prepojenia Obmedzené na Crosstalk a OJS alebo runtime: shiny. Veľmi silné – umožňuje prepojenie viacerých zdrojov údajov a vizualizácií.
Cena Bezplatné (open-source). Licencia vyžaduje predplatné.

Hlavné výhody Quarto:

  • Rýchlosť vykresľovania a responzívnosť: Quarto dashboardy, ktoré využívajú JavaScript (Crosstalk, summarywidget), fungujú priamo v prehliadači. Všetky zmeny vo filtroch alebo interaktívnych prvkoch sú extrémne rýchle, pretože prebiehajú na strane klienta.
  • Flexibilita formátovania: Quarto ponúka obrovské možnosti prispôsobenia dizajnu pomocou CSS a HTML, čo umožňuje vytvoriť úplne na mieru prispôsobené dashboardy, ktoré presne zodpovedajú vašim požiadavkám.
  • Jednoduchosť nasadzovania a zdieľania: Dashboardy vytvorené v Quarto je možné nasadiť ako statické stránky, napríklad na GitHub Pages. Nepotrebujete žiadne dodatočné servery ani licencie, čo šetrí čas aj financie.
  • Open-source riešenie: Na rozdiel od Power BI, ktoré vyžaduje platenú licenciu na plnohodnotné využitie, Quarto je úplne bezplatné a otvorené riešenie.

Obmedzenia:

  • Komplexné vizualizácie: Power BI umožňuje dynamicky zobrazovať dáta v interaktívnych vizualizáciách. Quarto je v tomto smere obmedzené, pretože jeho interaktívne funkcie (Crosstalk) fungujú iba v rámci podporovaných knižníc, ako sú DT, plotly alebo leaflet. Prípadne vyžadujú znalosť OJS. Pre komplexné vizualizácie je nutný runtime: shiny.

  • Použitie na profesionálne účely: Power BI je skôr považované za alternatívu k Shiny, a to najmä vďaka schopnosti spracovať veľké objemy dát z rôznych zdrojov. Quarto je vhodnejšie pre rýchlejšiu a menej komplexnú prezentáciu dát.

Porovnaním týchto dvoch nástrojov je zrejmé, že Quarto a Power BI majú rozličný use case. Quarto je ideálne na rýchlu tvorbu interaktívnych dashboardov a reportov, kde nie sú potrebné zložité transformácie dát alebo prepojenia medzi rôznymi zdrojmi údajov. Je vhodné pre používateľov, ktorí už spracovali dáta v R a chcú ich elegantne prezentovať. Power BI je naopak silným nástrojom na spracovanie dát a tvorbu robustných dashboardov s prepojením na rôzne zdroje údajov. Vďaka svojim analytickým schopnostiam a integrácii je často preferované pre profesionálne a podnikové riešenia.

Ak hľadáte nástroj na tvorbu dashboardov, rozhodnutie medzi Quarto a Power BI bude závisieť od konkrétnych potrieb. Zvážte rýchlosť, možnosti formátovania, spôsob spracovania dát a celkovú komplexitu riešenia, aby ste si vybrali ten najvhodnejší nástroj.

Príklad: Quarto Dashboard

Ak chcete vidieť Quarto dashboard v praxi, pozrite si môj interaktívny projekt:
Quarto Customers Dashboard.

Zdrojový kód je dostupný na GitHube:
GitHub repo.

Záver

Quarto a Shiny majú každý svoj ideálny spôsob použitia. Ak potrebujete plnú silu reaktivity, komplexné spracovanie dát a interakcie, Shiny je lepšia voľba. Na druhej strane, ak hľadáte elegantné a efektívne riešenie na tvorbu interaktívnych dashboardov bez zbytočnej zložitosti alebo využívať výhody jednoduchšieho nasadzovania, Quarto je skvelou alternatívou k Shiny. Je rýchle, jednoducho sa zdieľa a nevyžaduje server – vyskúšajte ho a uvidíte, ako jednoducho môžete prezentovať svoje dáta!

Popri Quarto a Shiny však existujú aj ďalšie alternatívy, ako napríklad Power BI a Tableau. Tieto nástroje sú obzvlášť vhodné pre profesionálne prostredia, kde je potrebné rýchlo vytvárať vizualizácie a analyzovať dáta z rôznych zdrojov bez nutnosti programovania.

  • Power BI: Silné analytické nástroje a jednoduché nasadzovanie, ale menej flexibilné možnosti formátovania.
  • Tableau: Vynikajúce vizualizačné možnosti a užívateľsky prívetivé prostredie, avšak nákladné a s obmedzenou podporou pokročilého programovania.

Flexibilita úprav pomocou HTML, CSS a JavaScript dáva Quarto náskok v možnostiach prispôsobenia dizajnu a funkčnosti oproti Power BI a podobným nástrojom. Preto si pri výbere nástroja premyslite, aké sú vaše požiadavky na interaktivitu, nasadzovanie a dizajn, aby ste si zvolili ten najvhodnejší nástroj pre váš projekt.

Exploratory Data Analysis v R: Nástroje a tipy pre úspešnú analýzu 150 150 cleandata

Exploratory Data Analysis v R: Nástroje a tipy pre úspešnú analýzu

V tomto blogu vám ukážem, ako efektívne pristupovať k Exploratory Data Analysis (EDA) v R. Prevediem vás základnými funkciami, ako aj pokročilými knižnicami na analýzu dát, vizualizácie a automatizované reporty. Ak chcete získať lepší prehľad o svojich dátach a zefektívniť analýzu, tento blog je pre vás.

eda-kniznice-v-r

Úvod

V tomto blogu si prejdeme niekoľko knižníc v R, ktoré slúžia na základnú analýzu dát, zvanú tiež Exploratory Data Analysis (EDA). EDA je dôležitým krokom v každom dátovom projekte, pretože nám umožňuje lepšie pochopiť štruktúru, kvalitu a rozloženie dát ešte pred tým, ako s nimi začneme ďalej pracovať, modelovať alebo robiť predikcie. Na ukážku budeme používať dataset zo série blogov o cenách nehnuteľností. Prvú časť venovanú získavaniu týchto dát najdete tu.

Funkcie na základný prehľad

base R

Ak potrebujeme zistiť rozmery našich dát, môžeme použiť funkciu dim():

dim(data)
#> [1] 12488    16

Tá nám vráti počet riadkov a stĺpcov, v tomto prípade 12 488 riadkov a 16 stĺpcov.

Ak chceme vidieť aj náhľad a dátový typ stĺpcov, máme k dispozícii funkciu str():

str(data)
#> sf [12,488 × 16] (S3: sf/tbl_df/tbl/data.frame)
#>  $ name_nsi         : chr [1:12488] "Štúrovo" "Štúrovo" "Štúrovo" "Štúrovo" ...
#>  $ price            : int [1:12488] 107000 105000 82000 102000 95000 82000 74900 64900 83000 96500 ...
#>  $ index            : num [1:12488] 8.3 8.25 8.25 8.25 8.25 8.25 8.25 8.25 8.25 8.25 ...
#>  $ environment      : num [1:12488] 9.1 9.1 9.1 9.1 9.1 9.1 9.1 9.1 9.1 9.1 ...
#>  $ quality_of_living: num [1:12488] 7.4 7.4 7.4 7.4 7.4 7.4 7.4 7.4 7.4 7.4 ...
#>  $ safety           : num [1:12488] 9.5 9.5 9.5 9.5 9.5 9.5 9.5 9.5 9.5 9.5 ...
#>  $ transport        : num [1:12488] 7 7 7 7 7 7 7 7 7 7 ...
#>  $ services         : num [1:12488] 9.3 9.3 9.3 9.3 9.3 9.3 9.3 9.3 9.3 9.3 ...
#>  $ relax            : num [1:12488] 7 7 7 7 7 7 7 7 7 7 ...
#>  $ condition        : chr [1:12488] "Partial reconstruction" "Complete reconstruction" "Partial reconstruction" "Complete reconstruction" ...
#>  $ area             : num [1:12488] 40 76 63 76.5 63 ...
#>  $ provision        : num [1:12488] 0 1 0 0 1 0 1 0 0 0 ...
#>  $ certificate      : chr [1:12488] NA "C" NA "none" ...
#>  $ type             : chr [1:12488] "1-room apartment" "3-room apartment" "2-room apartment" "3-room apartment" ...
#>  $ rooms            : num [1:12488] 1 3 2 3 2 2 2 2 2 3 ...
#>  $ district         : chr [1:12488] "Nové Zámky" "Nové Zámky" "Nové Zámky" "Nové Zámky" ...
#>  - attr(*, "sf_column")= chr "geometry"
#>  - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA NA NA NA NA NA NA NA NA NA ...
#>   ..- attr(*, "names")= chr [1:16] "name_nsi" "price" "index" "environment" ...

Tieto funkcie nám však nepovedia nič o rozložení dát, či a koľko máme chýbajúcich záznamov. Najzákladnejšia možnosť, ako získať popis premenných nášho dátového setu je funkcia summary():

summary(data)
#>    name_nsi             price            index        environment    
#>  Length:12488       Min.   : 22997   Min.   :3.300   Min.   : 2.700  
#>  Class :character   1st Qu.: 99990   1st Qu.:7.513   1st Qu.: 7.474  
#>  Mode  :character   Median :135000   Median :8.020   Median : 7.817  
#>                     Mean   :149723   Mean   :7.842   Mean   : 7.888  
#>                     3rd Qu.:180000   3rd Qu.:8.344   3rd Qu.: 8.386  
#>                     Max.   :600000   Max.   :9.500   Max.   :10.000  
#>                                      NA's   :2887    NA's   :2921    
#>  quality_of_living     safety         transport         services     
#>  Min.   : 2.700    Min.   : 2.000   Min.   : 2.000   Min.   : 2.000  
#>  1st Qu.: 8.372    1st Qu.: 7.661   1st Qu.: 7.900   1st Qu.: 7.375  
#>  Median : 8.863    Median : 8.600   Median : 8.600   Median : 8.251  
#>  Mean   : 8.743    Mean   : 8.155   Mean   : 8.355   Mean   : 7.981  
#>  3rd Qu.: 9.201    3rd Qu.: 9.488   3rd Qu.: 8.943   3rd Qu.: 8.800  
#>  Max.   :10.000    Max.   :10.000   Max.   :10.000   Max.   :10.000  
#>  NA's   :2921      NA's   :2921     NA's   :2921     NA's   :2921    
#>      relax        condition              area       provision    
#>  Min.   :2.000   Length:12488       Min.   :  3   Min.   :0.000  
#>  1st Qu.:4.867   Class :character   1st Qu.: 51   1st Qu.:0.000  
#>  Median :5.883   Mode  :character   Median : 63   Median :0.000  
#>  Mean   :5.774                      Mean   : 63   Mean   :0.163  
#>  3rd Qu.:6.750                      3rd Qu.: 74   3rd Qu.:0.000  
#>  Max.   :9.500                      Max.   :238   Max.   :1.000  
#>  NA's   :2921                                                    
#>  certificate            type               rooms         district        
#>  Length:12488       Length:12488       Min.   :1.000   Length:12488      
#>  Class :character   Class :character   1st Qu.:2.000   Class :character  
#>  Mode  :character   Mode  :character   Median :2.000   Mode  :character  
#>                                        Mean   :2.407                     
#>                                        3rd Qu.:3.000                     
#>                                        Max.   :5.000                     
#> 

Táto funkcia vracia niekoľko užitočných charakteristík ako minimálna hodnota, prvý a tretí kvartil, priemer, medián, maximálna hodnota a počet chýbajúcich hodnôt. Žiaľ, toto platí len pre kvantitatívne premenné. Pri textových je uvedený len počet riadkov. Rovnako nie je explicitne uvedený počet riadkov a stĺpcov. Všetky predchádzajúce funkcie majú však výhodu, že sú súčasťou základného R a netreba pre ne inštalovať žiadne knižnice. Ak sa však chceme dozvedieť o našich dátach viac, musíme hľadať iné možnosti. Buď to môžu byť vlastné nadefinované funkcie, ktoré si môžeme uložiť a používať v rôznych projektoch, alebo siahneme po externých knižniciach od iných autorov.

dplyr

data |> glimpse()
#> Rows: 12,488
#> Columns: 16
#> $ name_nsi          <chr> "Štúrovo", "Štúrovo", "Štúrovo", "Štúrovo", "Štúrovo…
#> $ price             <int> 107000, 105000, 82000, 102000, 95000, 82000, 74900, …
#> $ index             <dbl> 8.30, 8.25, 8.25, 8.25, 8.25, 8.25, 8.25, 8.25, 8.25…
#> $ environment       <dbl> 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.1, 9.…
#> $ quality_of_living <dbl> 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.4, 7.…
#> $ safety            <dbl> 9.5, 9.5, 9.5, 9.5, 9.5, 9.5, 9.5, 9.5, 9.5, 9.5, 9.…
#> $ transport         <dbl> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7…
#> $ services          <dbl> 9.3, 9.3, 9.3, 9.3, 9.3, 9.3, 9.3, 9.3, 9.3, 9.3, 9.…
#> $ relax             <dbl> 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7…
#> $ condition         <chr> "Partial reconstruction", "Complete reconstruction",…
#> $ area              <dbl> 40.00, 76.00, 63.00, 76.50, 63.00, 63.45, 64.00, 57.…
#> $ provision         <dbl> 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0…
#> $ certificate       <chr> NA, "C", NA, "none", "none", NA, NA, "none", NA, NA,…
#> $ type              <chr> "1-room apartment", "3-room apartment", "2-room apar…
#> $ rooms             <dbl> 1, 3, 2, 3, 2, 2, 2, 2, 2, 3, 3, 2, 3, 2, 3, 3, 3, 2…
#> $ district          <chr> "Nové Zámky", "Nové Zámky", "Nové Zámky", "Nové Zámk…

Dplyr je knižnica primárne určená na manipuláciu s dátami. Obsahuje však aj šikovnú funkciu glimpse(), ktorá má veľmi podobný výstup ako str(). Jej výhodou, okrem čitateľnejšieho formátu, je napr. to, že ak do nej zadáme parameter “0”, tak nám vráti štruktúru dát a typ stĺpcov avšak bez ich hodnôt. Toto môže byť výhodné, ak používame napr. chatbotov ako ChatGPT ale máme dôverné dáta.

data |> glimpse(0)
#> Rows: 12,488
#> Columns: 16
#> $ name_nsi          <chr> …
#> $ price             <int> …
#> $ index             <dbl> …
#> $ environment       <dbl> …
#> $ quality_of_living <dbl> …
#> $ safety            <dbl> …
#> $ transport         <dbl> …
#> $ services          <dbl> …
#> $ relax             <dbl> …
#> $ condition         <chr> …
#> $ area              <dbl> …
#> $ provision         <dbl> …
#> $ certificate       <chr> …
#> $ type              <chr> …
#> $ rooms             <dbl> …
#> $ district          <chr> …

skimr

Jednou z mojich obľúbených knižních na EDA je skimr a najmä funkcia skim():

skim(data)
Data summary
Name data
Number of rows 12488
Number of columns 16
_______________________
Column type frequency:
character 5
numeric 11
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
name_nsi 0 1.00 4 46 0 203 0
condition 3 1.00 12 23 0 6 0
certificate 7106 0.43 1 4 0 8 0
type 0 1.00 6 24 0 7 0
district 0 1.00 4 20 0 72 0

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
price 0 1.00 149723.10 72018.19 22997.0 99990.00 1.35e+05 1.80e+05 600000.0 ▇▆▁▁▁
index 2887 0.77 7.84 0.81 3.3 7.51 8.02e+00 8.34e+00 9.5 ▁▁▁▇▅
environment 2921 0.77 7.89 0.77 2.7 7.47 7.82e+00 8.39e+00 10.0 ▁▁▁▇▂
quality_of_living 2921 0.77 8.74 0.70 2.7 8.37 8.86e+00 9.20e+00 10.0 ▁▁▁▃▇
safety 2921 0.77 8.15 1.75 2.0 7.66 8.60e+00 9.49e+00 10.0 ▁▁▁▅▇
transport 2921 0.77 8.35 1.17 2.0 7.90 8.60e+00 8.94e+00 10.0 ▁▁▁▅▇
services 2921 0.77 7.98 1.30 2.0 7.38 8.25e+00 8.80e+00 10.0 ▁▁▂▇▇
relax 2921 0.77 5.77 1.47 2.0 4.87 5.88e+00 6.75e+00 9.5 ▂▆▇▇▁
area 0 1.00 63.00 20.42 3.0 51.00 6.30e+01 7.40e+01 238.0 ▃▇▁▁▁
provision 0 1.00 0.16 0.37 0.0 0.00 0.00e+00 0.00e+00 1.0 ▇▁▁▁▂
rooms 0 1.00 2.41 0.85 1.0 2.00 2.00e+00 3.00e+00 5.0 ▃▇▇▂▁

Táto funkcia vracia v tomto prípade tri prehladové tabuľky:

  • Prvá je sumár s názvom objektu, počtom riadkov a stĺpcov, a z toho počet numerických a textových.
  • Druhá obsahuje prehľad textových stĺpcov a ich vlastnosti, ako počet chýbajúcich záznamov, najmenší a najčastejší výskyt a počet unikátnych hodnôt. Tieto údaje sú dôležité, nielen kvôli “reasonability check” kontrole a prvotnému zhodnoteniu dátovej kvality, ale aj kvôli tomu, aby sme vedeli už dopredu plánovať stratégiu, ako pracovať s kardinalitou jednotlivých premenných.
  • Posledná tabuľka nám dáva podobné hodnoty ako funkcia summary pre číselné stĺpce, avšak navyše dostávame aj štandardnú odchýlku a histogram s rozložením hodnôt.

Ak by sme mali aj iný typ hodnôt, napríklad dátum, mali by sme prehľad aj preň.

summarytools

Summarytools je knižnica, ktorá umožňuje skutočne detailnú EDA. Má množstvo funkcií, ktoré sa dajú rôzne prispôsobovať našim potrebám. Prejdeme si niekoľko z nich.

dfSummary

Funkcia dfSummary() vytvorí súhrnnú tabuľku so štatistikami, frekvenciami a grafmi pre všetky premenné. Zobrazené informácie sú špecifické pre typ premennej (číselné premenné majú iné metriky ako napr. textové alebo dátumové).

print(dfSummary(data,
          graph.col = TRUE,
          graph.magnif = 0.75,
          style = "grid",
          plain.ascii = FALSE, 
          result = "asis",
          valid.col = FALSE), method = 'render', table.classes = 'st-small')

Data Frame Summary

data

Dimensions: 12488 x 16
Duplicates: 547
No Variable Stats / Values Freqs (% of Valid) Graph Missing
1 name_nsi [character]
1. Bratislava – mestská časť
2. Bratislava – mestská časť
3. Bratislava – mestská časť
4. Nitra
5. Žilina
6. Nové Zámky
7. Trnava
8. Banská Bystrica
9. Bratislava – mestská časť
10. Trenčín
[ 193 others ]
831 ( 6.7% )
546 ( 4.4% )
540 ( 4.3% )
368 ( 2.9% )
365 ( 2.9% )
340 ( 2.7% )
334 ( 2.7% )
319 ( 2.6% )
299 ( 2.4% )
281 ( 2.3% )
8265 ( 66.2% )
0 (0.0%)
2 price [integer]
Mean (sd) : 149723.1 (72018.2)
min ≤ med ≤ max:
22997 ≤ 135000 ≤ 6e+05
IQR (CV) : 80010 (0.5)
2129 distinct values 0 (0.0%)
3 index [numeric]
Mean (sd) : 7.8 (0.8)
min ≤ med ≤ max:
3.3 ≤ 8 ≤ 9.5
IQR (CV) : 0.8 (0.1)
118 distinct values 2887 (23.1%)
4 environment [numeric]
Mean (sd) : 7.9 (0.8)
min ≤ med ≤ max:
2.7 ≤ 7.8 ≤ 10
IQR (CV) : 0.9 (0.1)
120 distinct values 2921 (23.4%)
5 quality_of_living [numeric]
Mean (sd) : 8.7 (0.7)
min ≤ med ≤ max:
2.7 ≤ 8.9 ≤ 10
IQR (CV) : 0.8 (0.1)
112 distinct values 2921 (23.4%)
6 safety [numeric]
Mean (sd) : 8.2 (1.7)
min ≤ med ≤ max:
2 ≤ 8.6 ≤ 10
IQR (CV) : 1.8 (0.2)
120 distinct values 2921 (23.4%)
7 transport [numeric]
Mean (sd) : 8.4 (1.2)
min ≤ med ≤ max:
2 ≤ 8.6 ≤ 10
IQR (CV) : 1 (0.1)
135 distinct values 2921 (23.4%)
8 services [numeric]
Mean (sd) : 8 (1.3)
min ≤ med ≤ max:
2 ≤ 8.3 ≤ 10
IQR (CV) : 1.4 (0.2)
142 distinct values 2921 (23.4%)
9 relax [numeric]
Mean (sd) : 5.8 (1.5)
min ≤ med ≤ max:
2 ≤ 5.9 ≤ 9.5
IQR (CV) : 1.9 (0.3)
142 distinct values 2921 (23.4%)
10 condition [character]
1. Complete reconstruction
2. Development project
3. New building
4. Original condition
5. Partial reconstruction
6. Under construction
3773 ( 30.2% )
54 ( 0.4% )
3057 ( 24.5% )
1854 ( 14.8% )
3439 ( 27.5% )
308 ( 2.5% )
3 (0.0%)
11 area [numeric]
Mean (sd) : 63 (20.4)
min ≤ med ≤ max:
3 ≤ 63 ≤ 238
IQR (CV) : 23 (0.3)
2270 distinct values 0 (0.0%)
12 provision [numeric]
Min : 0
Mean : 0.2
Max : 1
0 : 10452 ( 83.7% )
1 : 2036 ( 16.3% )
0 (0.0%)
13 certificate [character]
1. A
2. B
3. C
4. D
5. E
6. F
7. G
8. none
1115 ( 20.7% )
884 ( 16.4% )
141 ( 2.6% )
20 ( 0.4% )
7 ( 0.1% )
2 ( 0.0% )
63 ( 1.2% )
3150 ( 58.5% )
7106 (56.9%)
14 type [character]
1. 1-room apartment
2. 2-room apartment
3. 3-room apartment
4. 4-room apartment
5. 5 or more room apartment
6. Studio
7. Two-room apartment
1565 ( 12.5% )
4605 ( 36.9% )
4960 ( 39.7% )
921 ( 7.4% )
55 ( 0.4% )
322 ( 2.6% )
60 ( 0.5% )
0 (0.0%)
15 rooms [numeric]
Mean (sd) : 2.4 (0.8)
min ≤ med ≤ max:
1 ≤ 2 ≤ 5
IQR (CV) : 1 (0.4)
1 : 1887 ( 15.1% )
2 : 4665 ( 37.4% )
3 : 4960 ( 39.7% )
4 : 921 ( 7.4% )
5 : 55 ( 0.4% )
0 (0.0%)
16 district [character]
1. Bratislava II
2. Bratislava IV
3. Bratislava V
4. Bratislava I
5. Senec
6. Bratislava III
7. Dunajská Streda
8. Nitra
9. Nové Zámky
10. Žilina
[ 62 others ]
1156 ( 9.3% )
660 ( 5.3% )
564 ( 4.5% )
540 ( 4.3% )
486 ( 3.9% )
476 ( 3.8% )
438 ( 3.5% )
402 ( 3.2% )
396 ( 3.2% )
382 ( 3.1% )
6988 ( 56.0% )
0 (0.0%)

Generated by summarytools 1.0.1 (R version 4.4.1)
2024-11-25

descr

Funkcia descr() vytvorí tabuľku s popisnou štatistikou.

print(descr(data,
      headings = FALSE,
      result = "asis",
      plain.ascii = FALSE) , method = 'render', table.classes = 'st-small')
area environment index price provision quality_of_
living
relax rooms safety services transport
Mean 63.00 7.89 7.84 149723.10 0.16 8.74 5.77 2.41 8.15 7.98 8.35
Std.Dev 20.42 0.77 0.81 72018.19 0.37 0.70 1.47 0.85 1.75 1.30 1.17
Min 3.00 2.70 3.30 22997.00 0.00 2.70 2.00 1.00 2.00 2.00 2.00
Q1 51.00 7.47 7.51 99990.00 0.00 8.37 4.87 2.00 7.66 7.38 7.90
Median 63.00 7.82 8.02 135000.00 0.00 8.86 5.88 2.00 8.60 8.25 8.60
Q3 74.00 8.39 8.34 180000.00 0.00 9.20 6.75 3.00 9.49 8.80 8.94
Max 238.00 10.00 9.50 600000.00 1.00 10.00 9.50 5.00 10.00 10.00 10.00
MAD 16.31 0.63 0.58 58562.70 0.00 0.62 1.38 1.48 1.33 1.11 0.81
IQR 23.00 0.91 0.83 80010.00 0.00 0.83 1.88 1.00 1.83 1.43 1.04
CV 0.32 0.10 0.10 0.48 2.27 0.08 0.25 0.35 0.21 0.16 0.14
Skewness 1.13 -0.84 -1.71 1.65 1.82 -1.57 -0.20 0.02 -1.54 -1.41 -2.04
SE.Skewness 0.02 0.03 0.02 0.02 0.02 0.03 0.03 0.02 0.03 0.03 0.03
Kurtosis 5.33 3.13 5.07 4.54 1.33 4.89 -0.13 -0.43 2.18 2.96 7.60
N.Valid 12488 9567 9601 12488 12488 9567 9567 12488 9567 9567 9567
Pct.Valid 100.00 76.61 76.88 100.00 100.00 76.61 76.61 100.00 76.61 76.61 76.61

Generated by summarytools 1.0.1 (R version 4.4.1)
2024-11-25

freq

Funkcia freq() vytvorí frekvenčnú tabuľku.

print(freq(data |> select(-name_nsi, -district), 
     plain.ascii = FALSE, 
     style = "rmarkdown",
     result = "asis"), method = 'render', table.classes = 'st-small')

Frequencies

select(data, -name_nsi, -district)$condition

Type: Character
Valid Total
condition Freq % % Cum. % % Cum.
Complete reconstruction 3773 30.22 30.22 30.21 30.21
Development project 54 0.43 30.65 0.43 30.65
New building 3057 24.49 55.14 24.48 55.12
Original condition 1854 14.85 69.99 14.85 69.97
Partial reconstruction 3439 27.55 97.53 27.54 97.51
Under construction 308 2.47 100.00 2.47 99.98
<NA> 3 0.024 100.00
Total 12488 100.00 100.00 100.00 100.00

select(data, -name_nsi, -district)$provision

Type: Numeric
Valid Total
provision Freq % % Cum. % % Cum.
0 10452 83.70 83.70 83.70 83.70
1 2036 16.30 100.00 16.30 100.00
<NA> 0 0.00 100.00
Total 12488 100.00 100.00 100.00 100.00

select(data, -name_nsi, -district)$certificate

Type: Character
Valid Total
certificate Freq % % Cum. % % Cum.
A 1115 20.72 20.72 8.93 8.93
B 884 16.43 37.14 7.08 16.01
C 141 2.62 39.76 1.13 17.14
D 20 0.37 40.13 0.16 17.30
E 7 0.13 40.26 0.056 17.35
F 2 0.037 40.30 0.016 17.37
G 63 1.17 41.47 0.50 17.87
none 3150 58.53 100.00 25.22 43.10
<NA> 7106 56.90 100.00
Total 12488 100.00 100.00 100.00 100.00

select(data, -name_nsi, -district)$type

Type: Character
Valid Total
type Freq % % Cum. % % Cum.
1-room apartment 1565 12.53 12.53 12.53 12.53
2-room apartment 4605 36.88 49.41 36.88 49.41
3-room apartment 4960 39.72 89.13 39.72 89.13
4-room apartment 921 7.38 96.50 7.38 96.50
5 or more room apartment 55 0.44 96.94 0.44 96.94
Studio 322 2.58 99.52 2.58 99.52
Two-room apartment 60 0.48 100.00 0.48 100.00
<NA> 0 0.00 100.00
Total 12488 100.00 100.00 100.00 100.00

select(data, -name_nsi, -district)$rooms

Type: Numeric
Valid Total
rooms Freq % % Cum. % % Cum.
1 1887 15.11 15.11 15.11 15.11
2 4665 37.36 52.47 37.36 52.47
3 4960 39.72 92.18 39.72 92.18
4 921 7.38 99.56 7.38 99.56
5 55 0.44 100.00 0.44 100.00
<NA> 0 0.00 100.00
Total 12488 100.00 100.00 100.00 100.00

Generated by summarytools 1.0.1 (R version 4.4.1)
2024-11-25

ctable

Funkcia ctable() vytvorí krížovú tabuľku pre dvojice kategorických premenných.

print(ctable(x = data$condition, 
       y = data$certificate, 
       prop = "n",
       totals   = FALSE, 
       headings = FALSE,
       result = "asis",
      plain.ascii = FALSE), method = 'render', table.classes = 'st-small')
certificate
condition A B C D E F G none <NA>
Complete reconstruction 104 275 52 5 3 1 17 1044 2272
Development project 29 1 1 0 0 0 0 1 22
New building 767 242 8 0 0 0 0 391 1649
Original condition 20 113 34 10 1 0 11 585 1080
Partial reconstruction 48 245 46 5 3 1 35 1106 1950
Under construction 147 8 0 0 0 0 0 20 133
<NA> 0 0 0 0 0 0 0 3 0

Generated by summarytools 1.0.1 (R version 4.4.1)
2024-11-25

stby

Ak potrebujeme analyzovať hodnoty v rámci skupín, môžeme použiť group_by() z knižnice dplyr a následne niektorú z vyššie uvedených funkcií alebo funkciu stby().

print(stby(data,
     INDICES = data$condition,
     FUN = descr, 
     stats = "fivenum", 
     transpose = TRUE,
     result = "asis",
      plain.ascii = FALSE), method = 'render', table.classes = 'st-small')

Descriptive Statistics

data

Group: condition = Complete reconstruction
N: 3773
Min Q1 Median Q3 Max
area 16.00 50.00 64.00 73.42 200.00
environment 2.70 7.47 7.82 8.39 10.00
index 3.70 7.66 8.10 8.40 9.40
price 27990.00 102950.00 134900.00 178000.00 599000.00
provision 0.00 0.00 0.00 0.00 1.00
quality_of_living 2.70 8.54 8.93 9.30 10.00
relax 2.00 5.05 6.29 6.80 9.40
rooms 1.00 2.00 3.00 3.00 5.00
safety 2.00 7.90 8.74 9.50 10.00
services 2.00 7.50 8.49 8.95 10.00
transport 2.00 7.90 8.60 8.94 10.00
Group: condition = Development project
N: 54
Min Q1 Median Q3 Max
area 30.00 42.40 59.38 68.48 109.00
environment 7.01 7.60 7.82 8.00 8.80
index 5.40 7.50 7.50 8.20 9.10
price 29000.00 145500.00 164904.00 194728.00 437000.00
provision 0.00 0.00 0.00 0.00 1.00
quality_of_living 7.70 7.70 8.46 9.34 9.70
relax 4.90 4.90 5.88 6.98 9.10
rooms 1.00 2.00 2.00 3.00 4.00
safety 6.70 8.28 8.70 9.49 10.00
services 6.50 8.22 8.90 9.16 9.90
transport 7.00 7.00 8.43 8.76 10.00
Group: condition = New building
N: 3057
Min Q1 Median Q3 Max
area 15.43 49.00 59.00 74.00 238.00
environment 2.70 7.39 7.75 8.32 9.80
index 3.30 7.00 7.66 8.21 9.50
price 56900.00 132500.00 169900.00 222900.00 599000.00
provision 0.00 0.00 0.00 0.00 1.00
quality_of_living 3.80 8.24 8.80 9.19 10.00
relax 2.00 4.07 5.55 6.75 9.50
rooms 1.00 2.00 2.00 3.00 5.00
safety 2.00 6.80 8.19 9.20 10.00
services 2.00 6.60 8.00 8.79 10.00
transport 2.00 7.70 8.60 8.94 10.00
Group: condition = Original condition
N: 1854
Min Q1 Median Q3 Max
area 17.00 55.00 65.00 74.64 235.00
environment 2.70 7.50 7.98 8.40 9.90
index 3.70 7.65 8.03 8.34 9.20
price 22997.00 85000.00 112700.00 149990.00 589000.00
provision 0.00 0.00 0.00 0.00 1.00
quality_of_living 4.00 8.50 8.90 9.20 10.00
relax 2.00 4.90 5.88 6.70 9.20
rooms 1.00 2.00 3.00 3.00 5.00
safety 2.00 7.81 8.60 9.50 10.00
services 2.00 7.44 8.25 8.86 10.00
transport 2.00 7.90 8.60 9.10 10.00
Group: condition = Partial reconstruction
N: 3439
Min Q1 Median Q3 Max
area 3.00 52.00 64.00 73.21 221.00
environment 2.70 7.50 7.90 8.39 9.90
index 3.30 7.60 8.02 8.34 9.40
price 26500.00 89900.00 117500.00 153000.00 600000.00
provision 0.00 0.00 0.00 0.00 1.00
quality_of_living 4.00 8.46 8.90 9.30 10.00
relax 2.00 4.95 5.88 6.68 9.40
rooms 1.00 2.00 3.00 3.00 5.00
safety 2.00 7.81 8.60 9.30 10.00
services 2.00 7.44 8.30 8.80 10.00
transport 2.00 7.90 8.54 8.94 10.00
Group: condition = Under construction
N: 308
Min Q1 Median Q3 Max
area 24.62 50.70 57.82 75.85 193.00
environment 6.50 7.77 8.12 8.32 9.20
index 4.00 7.00 7.21 7.60 9.00
price 61120.00 139945.00 184950.00 264250.00 569000.00
provision 0.00 0.00 0.00 0.00 1.00
quality_of_living 6.30 8.35 8.37 8.97 9.80
relax 2.00 3.85 4.09 5.60 9.10
rooms 1.00 2.00 2.00 3.00 4.00
safety 2.67 6.94 7.26 7.92 10.00
services 3.62 6.69 6.83 7.79 9.90
transport 2.00 8.05 8.55 8.67 10.00

Generated by summarytools 1.0.1 (R version 4.4.1)
2024-11-25

Väčšinu uvedených funkcií je možné použit na celý dátový set alebo aj na jednotlivé premenné. Knižnica summarytable tiež obsahuje rôzne preddefinované skupiny štatistických funkcií ako napr. “common”, “fivenum” a iné. Možno ste si všimli, že napr výstup z dfSummary je trochu ťažšie čitateľný, lebo jednotlivé hodnoty/riadky nie sú zarovnané. Toto je problém len pri generovaní cez quarto. Ak použijeme funkciu stview(), zobrazí sa vo “viewer” okne v Rstudiu oveľa čitateľnejší výstup.

dlookr

dlookr je knižnica určená pre komplexnú diagnostiku dát a ich prípravu. Obsahuje funkcie, ktoré vám pomôžu analyzovať kvalitu dát, identifikovať chýbajúce hodnoty, extrémne hodnoty (outliers) a štatistické anomálie. Je vhodná najmä pri príprave dát pre ďalšie analýzy alebo modelovanie. Teraz sa zameriame na funkcie pre potreby EDA, ale určite treba aspoň spomenúť napr.:

  • imputate_na(), ktorá ponúka rôzne spôsoby nahradenia chýbajúcich hodnôt.
  • imputate_outlier(), ktorá nahradí extrémne hodnoty podľa zvoleného spôsobu.
  • binning() a binning_by(), ktoré transformuje numerickú premennú na kategorickú tým, že vytvorí tzv. bins.

diagnose

Pomocou funkcie diagnose() môžeme rýchlo zistiť problémy vo svojich dátach, ako sú chýbajúce hodnoty, nulové hodnoty, unikátne hodnoty, či outliery.

diagnose(data)
#> # A tibble: 16 × 6
#>    variables        types missing_count missing_percent unique_count unique_rate
#>    <chr>            <chr>         <int>           <dbl>        <int>       <dbl>
#>  1 name_nsi         char…             0          0               203    0.0163  
#>  2 price            inte…             0          0              2129    0.170   
#>  3 index            nume…          2887         23.1             122    0.00977 
#>  4 environment      nume…          2921         23.4             122    0.00977 
#>  5 quality_of_livi… nume…          2921         23.4             114    0.00913 
#>  6 safety           nume…          2921         23.4             122    0.00977 
#>  7 transport        nume…          2921         23.4             137    0.0110  
#>  8 services         nume…          2921         23.4             143    0.0115  
#>  9 relax            nume…          2921         23.4             143    0.0115  
#> 10 condition        char…             3          0.0240            7    0.000561
#> 11 area             nume…             0          0              2270    0.182   
#> 12 provision        nume…             0          0                 2    0.000160
#> 13 certificate      char…          7106         56.9               9    0.000721
#> 14 type             char…             0          0                 7    0.000561
#> 15 rooms            nume…             0          0                 5    0.000400
#> 16 district         char…             0          0                72    0.00577

diagnose_numeric

Funkcia diagnose_numeric() analyzuje numerické premenné. Používa sa rovnako ako diagnose(), ale vracia viac informácií.

diagnose_numeric(data)
#> # A tibble: 11 × 10
#>    variables         min     Q1    mean median     Q3    max  zero minus outlier
#>    <chr>           <dbl>  <dbl>   <dbl>  <dbl>  <dbl>  <dbl> <int> <int>   <int>
#>  1 price          2.30e4 1.00e5 1.50e+5 1.35e5 1.80e5 6   e5     0     0     456
#>  2 index          3.3 e0 7.51e0 7.84e+0 8.02e0 8.34e0 9.5 e0     0     0     415
#>  3 environment    2.7 e0 7.47e0 7.89e+0 7.82e0 8.39e0 1   e1     0     0     251
#>  4 quality_of_li… 2.7 e0 8.37e0 8.74e+0 8.86e0 9.20e0 1   e1     0     0     245
#>  5 safety         2   e0 7.66e0 8.15e+0 8.6 e0 9.49e0 1   e1     0     0     803
#>  6 transport      2   e0 7.9 e0 8.35e+0 8.6 e0 8.94e0 1   e1     0     0     410
#>  7 services       2   e0 7.38e0 7.98e+0 8.25e0 8.8 e0 1   e1     0     0     377
#>  8 relax          2   e0 4.87e0 5.77e+0 5.88e0 6.75e0 9.5 e0     0     0      75
#>  9 area           3   e0 5.1 e1 6.30e+1 6.3 e1 7.4 e1 2.38e2     0     0     309
#> 10 provision      0      0      1.63e-1 0      0      1   e0 10452     0    2036
#> 11 rooms          1   e0 2   e0 2.41e+0 2   e0 3   e0 5   e0     0     0      55

diagnose_category

Funkcia diagnose_category() analyzuje kategorické premenné. Používa sa rovnako ako diagnose(), ale vracia viac informácií. Argument “top” špecifikuje počet hodnôt (levelov), ktoré funkcia vráti pre každú premennú. Preddefinovaná je hodnota. Ak je počet levelov menší ako zadaná “top” hodnota, tak funkcia vráti všetky.

diagnose_category(data, top = 3)
#> # A tibble: 15 × 6
#>    variables   levels                                    N  freq ratio  rank
#>    <chr>       <chr>                                 <int> <int> <dbl> <int>
#>  1 name_nsi    Bratislava - mestská časť Ružinov     12488   831  6.65     1
#>  2 name_nsi    Bratislava - mestská časť Petržalka   12488   546  4.37     2
#>  3 name_nsi    Bratislava - mestská časť Staré Mesto 12488   540  4.32     3
#>  4 condition   Complete reconstruction               12488  3773 30.2      1
#>  5 condition   Partial reconstruction                12488  3439 27.5      2
#>  6 condition   New building                          12488  3057 24.5      3
#>  7 certificate <NA>                                  12488  7106 56.9      1
#>  8 certificate none                                  12488  3150 25.2      2
#>  9 certificate A                                     12488  1115  8.93     3
#> 10 type        3-room apartment                      12488  4960 39.7      1
#> 11 type        2-room apartment                      12488  4605 36.9      2
#> 12 type        1-room apartment                      12488  1565 12.5      3
#> 13 district    Bratislava II                         12488  1156  9.26     1
#> 14 district    Bratislava IV                         12488   660  5.29     2
#> 15 district    Bratislava V                          12488   564  4.52     3

diagnose_outlier

Outliery môžu mať významný vplyv na štatistické analýzy a modelovanie. Funkcia diagnose_outlier() identifikuje extrémne hodnoty v dátach a zobrazí ich s prehľadom základných štatistík.

diagnose_outlier(data |> select(-rooms, -provision))
#> # A tibble: 9 × 6
#>   variables     outliers_cnt outliers_ratio outliers_mean with_mean without_mean
#>   <chr>                <int>          <dbl>         <dbl>     <dbl>        <dbl>
#> 1 price                  456          3.65      378694.   149723.      141045.  
#> 2 index                  415          3.32           5.30      7.84         7.96
#> 3 environment            251          2.01           5.57      7.89         7.95
#> 4 quality_of_l…          245          1.96           6.36      8.74         8.81
#> 5 safety                 803          6.43           3.63      8.15         8.57
#> 6 transport              410          3.28           4.64      8.35         8.52
#> 7 services               377          3.02           3.96      7.98         8.15
#> 8 relax                   75          0.601          2         5.77         5.80
#> 9 area                   309          2.47         130.       63.0         61.3

Pomocou funkcie plot_outlier() môžeme jednoducho vizualizovať rozloženie premenných s a bez identifikovaných odľahlých hodnôt.

data |> 
  plot_outlier(diagnose_outlier(data |> select(price, area)) |> 
                 filter(outliers_ratio >= 0.5) |> 
                 select(variables) |> 
                 unlist())

describe

Funkcia describe() je podobná funkcii summary(), no poskytuje podrobnejšie informácie. Aplikuje sa len na numerické dáta. Výstup tejto funkcie obsahuje štatistiky, ako sú priemerné hodnoty, medián, rozptyl, rôzne precentily, miery šikmosti a špicatosti, čo je veľmi užitočné pri identifikácii potenciálnych anomálií alebo trendov v dátach.

describe(data |> select(-rooms, -provision))
#> # A tibble: 9 × 26
#>   described_variables     n    na      mean        sd   se_mean     IQR skewness
#>   <chr>               <int> <int>     <dbl>     <dbl>     <dbl>   <dbl>    <dbl>
#> 1 price               12488     0 149723.   72018.    644.      8.00e+4    1.65 
#> 2 index                9601  2887      7.84     0.812   0.00828 8.31e-1   -1.71 
#> 3 environment          9567  2921      7.89     0.765   0.00782 9.12e-1   -0.845
#> 4 quality_of_living    9567  2921      8.74     0.703   0.00719 8.29e-1   -1.57 
#> 5 safety               9567  2921      8.15     1.75    0.0179  1.83e+0   -1.55 
#> 6 transport            9567  2921      8.35     1.17    0.0120  1.04e+0   -2.04 
#> 7 services             9567  2921      7.98     1.30    0.0133  1.43e+0   -1.41 
#> 8 relax                9567  2921      5.77     1.47    0.0150  1.88e+0   -0.201
#> 9 area                12488     0     63.0     20.4     0.183   2.3 e+1    1.13 
#> # ℹ 18 more variables: kurtosis <dbl>, p00 <dbl>, p01 <dbl>, p05 <dbl>,
#> #   p10 <dbl>, p20 <dbl>, p25 <dbl>, p30 <dbl>, p40 <dbl>, p50 <dbl>,
#> #   p60 <dbl>, p70 <dbl>, p75 <dbl>, p80 <dbl>, p90 <dbl>, p95 <dbl>,
#> #   p99 <dbl>, p100 <dbl>

normality

Funkcia normality() aplikuje Shapiro-Wilk test

normality(data |> select(-rooms, -provision))
#> # A tibble: 9 × 4
#>   vars              statistic  p_value sample
#>   <chr>                 <dbl>    <dbl>  <dbl>
#> 1 price                 0.885 1.62e-51   5000
#> 2 index                 0.879 1.03e-47   5000
#> 3 environment           0.956 1.71e-32   5000
#> 4 quality_of_living     0.897 5.00e-45   5000
#> 5 safety                0.836 9.95e-53   5000
#> 6 transport             0.839 1.96e-52   5000
#> 7 services              0.897 4.68e-45   5000
#> 8 relax                 0.984 1.78e-20   5000
#> 9 area                  0.928 6.07e-44   5000

Pomocou funkcie plot_normality() môžeme jednoducho vizualizovať pôvodné rozloženie premenných a rozloženie po log a sqrt transformácii.

plot_normality(data |> select(safety, relax))

Funkcie na korelačnú analýzu

Korelácia je väzba (závislosť) medzi dvomi alebo viacerými znakmi v štatistickom súbore. Pokiaľ sa jedna z náhodných veličín mení, mení sa aj druhá a naopak. Pokiaľ sa medzi dvoma náhodnými procesmi identifikuje korelácia, je pravdepodobné, že na sebe závisia. Z korelácie náhodných procesov alebo náhodných veličín však nemožno usudzovať príčinný vzťah. Teda jeden z nich nemusí byť príčinou a druhý následkom.

corrplot

Corrplot je pravdepodobne najznámejšia knižnica na korelačnú analýzu v R. Veľmi jednoducho sa používa a poskytuje bohaté možnosti, keďže má asi 50 parametrov. Vo väčšine prípadov môžeme získať graf korelačnej matice iba s jedným riadkom kódu.

m <- cor(data |> select(where(is.numeric)) |> select(-rooms, -provision) |> drop_na())

corrplot.mixed(m, order = 'AOE')

Príklad korelačnej matice vytvorenej pomocou knižnice corrplot

GGally

GGally je nadstavba nad ggplot2, ktorá umožňuje vytvárať párové grafy (pair plots), ktoré sú užitočné na identifikáciu vzťahov medzi rôznymi premennými. Zvlášť praktická je pri analýze veľkých datasetov s viacerými numerickými premennými.

ggpairs(data |> select(where(is.numeric)) |> select(-rooms, -provision) |> drop_na())

Príklad základnej korelačnej matice vytvorenej pomocou knižnice ggpairs

ggpairs(data |> select(price, index, area, type) |> filter(type %in% c("1-room apartment", "2-room apartment", "3-room apartment")) |> drop_na(), 
        ggplot2::aes(colour = type))

Príklad korelačnej matice vytvorenej pomocou knižnice corrplot doplnenej o ggplot2 funkcionality

PerformanceAnalytics

PerformanceAnalytics je knižnica zameraná na ekonometrickú analýzu výkonnosti a rizík, pričom sa často využíva najmä vo finančnom sektore. Obsahuje rôzne obsiahly balík nástrojov, okrem iného aj na vizualizáciu korelačných matíc. Funkcia chart.Correlation() je veľmi užitočná na vizualizáciu korelácie v podobe párových grafov, ktoré zobrazujú nielen samotnú koreláciu, ale aj rozloženie hodnôt.

chart.Correlation(data |> select(where(is.numeric)) |> select(-rooms, -provision) |> drop_na(), 
                  histogram = TRUE)

Príklad korelačnej matice vytvorenej pomocou knižnice PerformanceAnalytics

correlationfunnel

Correlationfunnel pomáha vizualizovať a analyzovať vzťahy medzi jednotlivými premennými a cieľovou premennou vo forme grafu. Numerické premenné sa konvertujú do kategórií (bins) a tie následne diskrétizuje pomocou procesu one-hot kódovania.

data |> 
  drop_na() |> 
  select(-name_nsi,
         -district) |> 
  mutate(across(where(is.numeric), round, 2)) |> 
  binarize(n_bins = 5, thresh_infreq = 0.01, name_infreq = "OTHER", one_hot = TRUE) |> 
  correlate(`price__-Inf_96100`) |> 
  plot_correlation_funnel()

Výstup z knižnice correlationfunnel ukazuje vzťah medzi cieľovou premennou a zvyšnými premennými

dlookr

Opäť sa vrátime aj ku knižnici dlookr a tentoraz k funkcii correlate(), ktorá počíta korelačný koeficient medzi dvojicami číselných premenných.

data |> select(where(is.numeric)) |> select(-rooms, -provision) |> drop_na() |> dlookr::correlate() |> mutate(coef_corr = round(coef_corr, 3))
#> # A tibble: 72 × 3
#>    var1              var2  coef_corr
#>    <fct>             <fct>     <dbl>
#>  1 index             price     0.116
#>  2 environment       price    -0.228
#>  3 quality_of_living price     0.193
#>  4 safety            price     0.1  
#>  5 transport         price     0.176
#>  6 services          price     0.178
#>  7 relax             price     0.248
#>  8 area              price     0.534
#>  9 price             index     0.116
#> 10 environment       index     0.125
#> # ℹ 62 more rows

Vizualizovať výsledky môžeme jednoducho pridaním plot().

data |> select(where(is.numeric)) |> select(-rooms, -provision) |> drop_na() |> dlookr::correlate() |> plot()

Príklad korelačnej matice vytvorenej pomocou knižnice dlookr

Funkcie na vytvorenie statických reportov

dlookr

Aj v tejto sekcii ponúka dlookr funkcie, ktoré vieme využiť.

Prvou je diagnose_paged_report(), druhá je špecificky určená na EDA – diagnose_paged_report() a tretia transformation_paged_report(), ktorá obsahuje imputáciu chýbajúcich hodnôt a outlierov, transformácie rozdelenia a binning.

DataExplorer

DataExplorer je knižnica, ktorá umožnuje jednoducho vytvárať statické reporty s prehľadmi dát. Obsahuje funkcie na automatickú analýzu a vizualizáciu dát, čo môže byť užitočné pri vytváraní EDA reportov pre tím alebo klientov.

SmartEDA

SmartEDA je ďalšia knižnica určená na rýchlu a jednoduchú tvorbu reportov o dátach. Poskytuje rôzne funkcie na sumarizáciu dát a ich distribúcie a dokáže generovať automatické reporty vo forme PDF alebo HTML.

Funkcie na vytvorenie dynamických Shiny reportov

GWalkR

GWalkR poskytuje rozhranie na vizualizáciu dát v R prostredníctvom interaktívnych grafov a tabuliek. Pomocou tejto knižnice je možné vytvoriť dynamické analýzy s drag-and-drop funkciounalitou. Dizajnovo je inšpirovaná Tableau-om.

esquisse

Esquisse je nástroj na vizualizáciu dát s intuitívnym drag-and-drop rozhraním postavený na knižnici ggplot2. Používateľom umožňuje vytvárať grafy bez nutnosti písania kódu, čo je ideálne pre začiatočníkov. Navyše umožnuje kopírovať vygenerovaný kód a ďalej ho použiť v analýze.

explore

Explore poskytuje jednoduché rozhranie pre dynamickú analýzu dát pomocou Shiny. Používateľ môže interaktívne prechádzať a analyzovať jednotlivé premenné, preskúmať ich vzťah k cieľovej premennej, vytvoriť rozhodovací strom alebo vytvoriť plne automatizovaný prehľad všetkých premenných.

radiant

Radiant je komplexný nástroj na exploratívnu analýzu, ktorý umožňuje prístup k rôznym analytickým metódam prostredníctvom Shiny. Používateľ môže jednoducho analyzovať dáta, vytvárať grafy a exportovať výsledky v rôznych formátoch, ktoré sú vhodné na ďalšie spracovanie. Používateľ má možnosť pridat vlastný R kód. Primárne je táto knižnica zaneraná na analýzu biznisových dát a na podporu rozhodovania na ich základe.

Je to najkomplexnejší nástroj z nášho zoznamu.

Záver

Exploratory Data Analysis (EDA) je kľúčovou súčasťou každej dátovej analýzy, či už sa jedná o predikčný model, klasifikáciu, alebo len detailnejšie pochopenie dát. Dôkladná analýza dát nám umožňuje lepšie pochopiť vzťahy medzi premennými, odhaliť potenciálne problémy a chyby a rozhodnúť sa, ktoré údaje sú pre naše účely relevantné. EDA nám tiež pomáha určiť, aké kroky potrebujeme urobiť pre čistenie a prípravu dát na ďalšie analýzy alebo modelovanie. Bez správneho pochopenia našich dát, nemôžeme robiť informované rozhodnutia o tom, ktoré modely použiť, aké premenné zahrnúť a aké kroky sú potrebné na prípravu dát. EDA nám pomáha odhaliť nekonzistencie a anomálie, ktoré by mohli ovplyvniť kvalitu našich výsledkov. EDA nie je jednorazová aktivita – je to proces, ktorý sa opakuje počas celého dátového projektu.

V tomto blogu sme sa venovali rôznym prístupom a nástrojom, ktoré môžeme použiť na vykonanie EDA v R. Začali sme s jednoduchými základnými funkciami, ako sú dim(), str() a summary(), ktoré sú užitočné pre rýchly prehľad o štruktúre a štatistike dát, a prešli sme na pokročilejšie knižnice ako dplyr, skimr, a summarytools, ktoré nám umožňujú získať detailné štatistiky, vizualizácie a reporty pre lepšie pochopenie dát.

Rôzne knižnice pre rôzne potreby

Každá z prezentovaných knižníc má svoje výhody a použitie závisí od našich potrieb a skúseností s R:

  • base R poskytuje základné nástroje bez potreby inštalácie ďalších balíčkov, ideálne na rýchle prehliadnutie dát.
  • dplyr a skimr ponúkajú efektívne možnosti na sumarizáciu dát s dôrazom na čitateľnosť a použiteľnosť.
  • summarytools umožňuje detailnú analýzu s pekne štruktúrovanými výstupmi, ktoré sú vhodné pre prezentácie a reporty.
  • DataExplorer a SmartEDA nám umožňujú automatizovať časť práce s EDA, čím šetríme čas pri vytváraní rozsiahlych reportov.
  • corrplot, GGally, PerformanceAnalytics a correlationfunnel ponúkajú rôzne možnosti na analýzu vzťahov medzi premennými pomocou vizualizácií.

Využitie v praxi

Každý z týchto nástrojov sa môže hodiť v rôznych fázach projektu. Pri prvotnom skúmaní dát môžeme začať so základnými funkciami na zistenie rozmerov a štruktúry dát. Ako sa hlbšie ponárame do údajov, môžeme využiť knižnice ako skimr alebo summarytools pre podrobnejší prehľad, či už hľadáme anomálie, chýbajúce hodnoty, alebo outliery.

Korelačné analýzy pomocou knižníc ako corrplot alebo PerformanceAnalytics, nám pomáhajú porozumieť vzťahom medzi premennými, čo je veľmi užitočné pri identifikovaní dôležitých faktorov, ktoré by mohli ovplyvniť naše modely alebo výsledky analýzy.

Automatizované reporty pomocou DataExplorer alebo SmartEDA nám šetria veľa času, keď potrebujeme opakovane analyzovať rôzne dataset-y alebo pri zdieľaní informácií s kolegami či klientmi, ktorí nemusia byť oboznámení s R, ale ocenia prehľadné a čitateľné reporty.

Vizualizácie a interaktivita

Vizualizácia je neoddeliteľnou súčasťou EDA, a práve preto sme zahrnuli knižnice ako GGally, esquisse alebo PerformanceAnalytics, ktoré poskytujú rôzne možnosti od jednoduchých párových grafov až po sofistikované korelačné mapy. Interaktívne vizualizácie v Shiny aplikáciách umožňujú nielen lepšie pochopiť vzťahy v dátach, ale tiež prezentovať tieto informácie iným osobám v prehľadnej forme, čím zjednodušujú diskusie a rozhodovanie.

Aký prístup zvoliť?

Pre začiatočníkov je dôležité začať s jednoduchými funkciami a krok po kroku sa oboznamovať s nástrojmi, ktoré im R ponúka. Základné funkcie v R sú výborným začiatkom. Ak už máme určitý základ a chceme urobiť EDA efektívnejšie a podrobnejšie, knižnice ako dplyr, skimr, alebo summarytools ponúkajú výkonné a ľahko použiteľné nástroje. Ak pracujete s veľkými dataset-mi, môžete oceniť knižnice a automatizované nástroje, ktoré šetria čas a zvyšujú efektivitu. Ktorý z nástrojov teda zvoliť? Odpoveď je klasické “to záleží…”. A záleží to na mnohých faktoroch ako osobná preferencia, špecifickosť projektu, typ dát atď. Najlepšie je oboznámiť sa s tými nástrojmi, ktoré nám dávajú najväčší zmysel a následne ich zaradiť do “toolboxu”, ak sa osvedčili.

Vývoj Shiny aplikácie na optimalizáciu trás 150 150 cleandata

Vývoj Shiny aplikácie na optimalizáciu trás

V tomto blogu vám ukážem, ako som vytvoril Shiny aplikáciu na optimalizáciu trás pomocou R programovania a API služby HERE. Tento projekt je dôkazom, že Shiny dokáže viac než len dashboardy – umožňuje nám budovať plnohodnotné webové aplikácie. Spolu sa pozrieme na základné funkcie aplikácie a na to, ako rieši rôzne výzvy spojené s optimalizáciou trás.

router_app_blog

Aplikácia pre Optimalizáciu Trás

Shiny aplikácia, ktorej sa budeme venovať, je vytvorená pomocou frameworku Rhino od spoločnosti Appsilon. Táto Shiny webaplikácia slúži na optimalizáciu trás pomocou API služby od HERE. Aplikácia je plne vytvorená v programovacom jazyku R s využitím rôznych R knižníc.

UI aplikácie

Aplikácia je určená pre používateľov, ktorí potrebujú plánovať trasy medzi viacerými miestami, pričom zohľadňuje aktuálne dopravné podmienky a preferencie používateľa. Aplikácia umožňuje jednoduchý vstup adries a ďalších parametrov, automatické geokódovanie a vizualizáciu výslednej trasy na mape.

Je navrhnutá ako Proof of Concept (PoC) v rámci vývoja aplikácií v Shiny a R programovaní, a preto má určité obmedzenia. Premávka sa zohľadňuje len pri úvodnom určení poradia, keď sa všetky trasy porovnávajú v rovnakom čase odchodu. Pri tvorbe poradia sa však nezohľadňuje zmena dopravy pri druhej, tretej a ďalších trasách. Zmena dopravnej situácie je zahrnutá až v čase výpočtu finálnej trasy.

Vstupné parametre v Shiny aplikácii

Používateľ má možnosť zadať nasledujúce parametre pre optimalizáciu trasy:

  • Čas odchodu: Používateľ môže zadať čas a dátum odchodu z prvého miesta.
  • Typ optimalizácie: Trasu možno optimalizovať na základe najkratšej vzdialenosti alebo najkratšieho času potrebného na prejdenie.
  • Adresy miest: Hlavnou podmienkou pre výpočet trasy je zadanie adries. Používateľ vkladá adresy priamo do tabuľky.
  • Názov miesta: Pre lepšiu orientáciu môže používateľ zadať aj názov miesta, ktorý bude zobrazený v mape.
  • Štartovacie a koncové miesto: Používateľ môže označiť, ktoré miesto je štartovacie a ktoré koncové.

Adresy sa vkladajú do tabuľky a po ich zadaní sa nedajú editovať. Na druhej strane, riadky je možné odstrániť (pravým klikom na riadok) alebo pridať nové cez kontextové menu. Okrem toho aplikácia umožňuje hromadné vloženie adries, napríklad cez copy-paste priamo z Excelu. Shiny aplikácia spracováva tieto údaje s ohľadom na technické limity API volaní. Je dôležité, aby v jednej bunke bola vždy jedna adresa a táto adresa neobsahovala špeciálne znaky.

Veľkosť tabuľky, do ktorej používateľ zadáva adresy, je obmedzená na 4 záznamy. Toto obmedzenie bolo zavedené z dôvodu, že máme dostupných len 1000 volaní API denne pre HERE platformu. Každá požiadavka na trasu medzi bodmi spotrebúva tieto volania, a preto je nutné počet adries obmedziť, aby sme neprekročili limity dostupných volaní.

Aj napriek tomuto obmedzeniu je aktuálna veľkosť tabuľky dostatočná pre účely Proof of Concept (PoC), kde je cieľom otestovať a overiť základnú funkcionalitu aplikácie a jej schopnosť vykonávať optimalizáciu trás.

Geokódovanie adries

Všetky vložené adresy sa automaticky geokódujú (proces prevodu adries na geografické súradnice) pomocou OpenStreetMap (OSM) API. Po úspešnom geokódovaní sa jednotlivé miesta zobrazia na mape s príslušným označením. Používateľ tak môže vidieť presné pozície všetkých adries, ktoré zadal. Ak sa na mape niektorý bod neukáže, geokódovanie neprebehlo úspešne a riadok treba zmazať a pridať nový s presnejšou adresou. Štartovacie miesto a koncové miesto majú odlíšené značenie. Proces geokódovania môže trvať približne 1 sekundu na každú vloženú adresu.

Výpočet trasy

Aplikácia využíva R skript na optimalizáciu poradia miest podľa problému obchodného cestujúceho (TSP). Tým sa zabezpečí, že poradie miest je optimálne, hoci samotný výpočet trás medzi jednotlivými bodmi využíva HERE API. V tomto kroku sa využíva heuristický algoritmus, ktorý zohľadňuje celkovú trasu, čím predchádza suboptimálnym výsledkom, ktoré by mohli vzniknúť, ak by sme len postupne spájali najbližšie miesta.

To znamená, že HERE API slúži len na výpočet jednotlivých segmentov trasy medzi bodmi, ale optimalizáciu celkovej trasy robí samotná aplikácia.

Po zadaní všetkých potrebných parametrov môže používateľ spustiť výpočet optimálnej trasy stlačením tlačidla “Vypočítaj trasu”. Aplikácia následne vypočíta ideálne poradie miest na základe zvoleného parametra optimalizácie (či už podľa času alebo vzdialenosti).

Aplikácia automaticky pridáva 10 minútový prestoj ku každému miestu, aby sa zohľadnil čas potrebný na parkovanie a presun od auta na miesto stretnutia a späť. Okrem toho, výpočet trasy zohľadňuje aktuálnu dopravnú situáciu a premávku podľa času odchodu z jednotlivých miest.

Výpočet trasy trvá niekoľko sekúnd, avšak čas potrebný na spracovanie sa nedá presne odhadnúť, keďže závisí od počtu miest, ktoré je potrebné zvážiť.

Zobrazenie trasy na mape

Po vypočítaní trasy sa výsledná optimalizovaná trasa zobrazí na mape. Na mape sa zobrazí aj legenda, ktorá vysvetľuje poradie trás a zobrazuje jednotlivé úseky cesty. Používateľ môže tiež pohybom myši nad jednotlivými miestami zobraziť podrobnosti o danej lokalite (tzv. ‘on hover’ popis).

Používateľ má možnosť zobraziť podrobné informácie o vypočítanej trase stlačením tlačidla Detaily trasy. V zobrazenom okne sú k dispozícii nasledujúce informácie pre každé miesto:

  • Názvy miest odchodu a príchodu.
  • Čas odchodu z miesta,
  • Čas príchodu na miesto,
  • Dĺžka trasy v kilometroch,
  • Trvanie cesty v minútach.

Tieto údaje je možné jednoducho exportovať do formátov xlsx alebo csv, čo umožňuje ich ďalšie spracovanie alebo použitie.

Problémy, alternatívne služby a knižnice

Pri vývoji tejto Shiny webaplikácie v R sme narazili na problém, že matrix routing nie je podporovaný pre nové API kľúče služby HERE, čo potvrdil aj tvorca knižnice hereR. Toto je zásah zo strany HERE. Tento problém znamená, že momentálne je potrebné vykonať až n! dotazov na získanie matice n * n pre optimalizáciu trasy, zatiaľ čo pomocou matrix routing API by stačil len jeden dotaz. Free účet služby HERE pritom umožňuje len 1 000 dotazov za jeden deň, čo vytvára vysoké nároky na počet volaní. Na druhej strane, aplikácia zostáva časovo relatívne rýchla, no je obmedzená počtom volaní API.

Existujú aj alternatívne riešenia:

  • Google Maps: Poskytuje veľmi presné údaje o cestách, dopravnej situácii a trasovaní, no je nákladnejšie pri vyšších objemoch požiadaviek a má vlastné obmedzenia, čo sa týka počtu volaní.
  • Mapbox : Ponúka podobné služby ako HERE, vrátane optimalizácie trás a geokódovania. Môže byť dobrou alternatívou pre menšie projekty, pričom má flexibilné plány pre vývojárov.
  • OpenRouteService: Tento open-source nástroj je vhodný pre tých, ktorí potrebujú robustnú alternatívu s menšími obmedzeniami, aj keď môže byť menej presný v niektorých oblastiach ako komerčné riešenia.

Zhrnutie

Táto aplikácia je navrhnutá ako Proof of Concept (PoC), čo znamená, že jej cieľom je demonštrovať základné funkcie a možnosti optimalizácie trás v reálnom čase pomocou Shiny a R programovania. V tejto fáze vývoja ide predovšetkým o overenie technickej realizovateľnosti a schopnosti integrovať služby, ako je API od HERE a geokódovanie cez OpenStreetMap (OSM).

Aplikácia poskytuje základný súbor funkcií a môže byť ďalej rozšírená o pokročilé možnosti, ako sú rozšírené filtre pre optimalizáciu trás, lepšia správa miest alebo integrácia ďalších dátových zdrojov.

Video s ukážkou základnej funkcionality nájdete na YouTube.

Efektívne vizualizácie dát pomocou Gestalt princípov 150 150 cleandata

Efektívne vizualizácie dát pomocou Gestalt princípov

Gestalt princípy zohrávajú kľúčovú úlohu pri tvorbe zrozumiteľných vizualizácií dát. Tento článok skúma, ako tieto princípy pomáhajú organizovať vizuálne prvky tak, aby efektívne komunikovali informácie a minimalizovali kognitívne zaťaženie užívateľa. Prostredníctvom príkladov v R je ukázané, ako správna aplikácia týchto princípov zvyšuje čitateľnosť a prehľadnosť grafov, čo vedie k lepšiemu porozumeniu prezentovaných dát.

gestalt-principles

Úvod

Gestalt princípy sú základné pravidlá, ktoré vysvetľujú, ako ľudia vnímajú vizuálne elementy ako celok. Svoj pôvod majú v Gestalt (celostnej) psychológii zo začiatku 20. storočia. Základnú myšlienku vyslovil Kurt Koffka: “The whole is something else than the sum of its parts”, čiže celok je niečo iné, ako suma jeho častí. Tieto princípy sú kľúčové pri tvorbe efektívnych a zrozumiteľných vizualizácií dát (čiže takých, ktoré jasne komunikujú, čo je “signál” v našich dátach). Dobrá vizualizácia je vytváraná ako celok. Jej jednotlivé časti meníme takým spôsobom, aby tento celok jasne komunikoval hlavnú myšlienku a nevytváral zbytočne veľké kognitívne zaťaženie užívateľa. V tomto článku sa pozrieme na 6 všeobecne rozoznávaných Gestalt princípov a ukážeme si, ako ich aplikovať pri vizualizácii dát pomocou R.

Princíp blízkosti (proximity)

Objekty, ktoré sú blízko pri sebe máme tendenciu považovať za časť jednej skupiny.

Gestalt princíp blízkosti

V BI tento princíp môžeme využiť napr.v dizajne reportov. Aj tak jednoduchý element ako medzera medzi vizuálmi dokáže jednoducho sprehľadniť celý report. Oblasť filtrov, KPI kariet, grafov alebo tabuliek nepotrebujú špeciálne orámovanie. Stačí ich rozumne vzdialiť od seba a efekt je rovnaký a navyše čistejší.

Princíp podobnosti (similarity)

Objekty, ktoré maju podobný tvar, farbu alebo veľkosť sú vnímané ako jedna skupina. Tento princíp využíva napr. PowerBI v základnom dizajne tabuliek. V nich sa farba pozadia riadkov striedavo mení medzi bielou a sivou, čo pomáha čítať riadky, najmä ak je tabuľka široká. Typicky tento princíp využívame pri porovnávaní rôznych kategórií, ktorým priraďujeme rôznu farbu.

Gestalt princíp podobnosti

Princíp oblasti/ohraničenia (enclosure)

Objekty, ktoré sú spoločne uzavreté, považujeme za súčasť jednej skupiny. Uzavretie nemusí byť výrazné, aby sme dokázali využiť tento princíp. Vďaka tomuto princípu môžeme upriamiť pozornosť na tú časť dát, ktorú považujeme za najdôležitejšiu.

Gestalt princíp ohraničenia

Princíp uzavretosti (closure)

Tento princíp asi najlepšie vystihuje citát z úvodu: “The whole is something else than the sum of its parts”. Na obrázku nižšie ako prvé zbadáme kruh. Nerozmýšlame nad ním ako množstvom čiar, ale považujeme ho za celok. V našich mysliach máme množstvo takýchto konštruktov. Rovnako, ak nejaká časť celku chýba, dokážeme si ju podvedome doplniť.

Gestalt princíp uzavretosti

V praxi vieme tento princíp použiť pri odstraňovaní zbytočných elementov ako orámovanie, farebné pozadie, vodiace čiary atď. Napriek tomu užívateľ bez problému rozozná, o aký typ vizualizácie sa jedná a informácia v nej môže vďaka čistejsiemu dizajnu vyniknúť viac.

Princíp plynulosti (continuity)

Princíp plynulosti hovorí, že ľudia majú tendenciu sledovať hladké kontinuálne vzory. Toto môžeme využiť pri čiarových grafoch, kde plynulé línie pomáhajú sledovať trendy v dátach. Druhou možnou aplikáciou je zoraďovanie podľa hodnoty. Pri doplnkových elementoch ako nadpis, podnadpis, značenie osí atď. by mali mať rovnaké zarovnanie a odsadenie.

Gestalt princíp plynulosti

Princíp prepojenia (connection)

Posledný princíp hovorí, že objekty, ktoré sú prepojené, vnímame ako jednu entitu. Toto môžeme aplikovať pri vizualizáciách, kde sú dátové body prepojené čiarami alebo inými vizuálnymi prvkami ako čiarové a pásové grafy, “slope” grafy a iné. Prepojenie vyvoláva väčšinou silnejšiu asociáciu ako tvar alebo farba, ale menšiu ako ohraničenie.

Gestalt princíp prepojenia

Praktický príklad

Pozrime sa na príklad aplikácie rôznych princípov a ako menia naše vnímanie.

Začneme s bodovým grafom.

Základný graf

Pri prvom pohľade sa zrejme jedná o zobrazenie dvoch skupín, keďže v každom mesiaci máme dve hodnoty. Nevieme ale určiť, kam jednotlivé body patria, či existuje nejaký signál v dátach. Skôr to vyzerá na náhodný zhluk bodov.

Pri aplikácii princípu podobnosti (tvar a farba) sa čitateľnosť aj množstvo informácií, ktoré vieme vyčítať, výrazne zvyšuje.

Základný graf + princíp podobnosti

Jedna skupina dosahuje vyššie hodnoty na začiatku aj konci roka, mesiace apríl až jún ma však slabé. Druhá skupina má naopak mesiace apríl až jún silnejšie, v máji je pritom rozdiel najväčší z celého roka. Napriem tomuto zlepšeniu sa graf stále nečíta veľmi dobre. Body príliš skáču a je ťažké udržat na nich pozornosť.

Skúsme teda ešte aplikovať princíp prepojenia.

Základný graf + princíp podobnosti + princíp prepojenia

Čitateľnosť je oveľa ľahšia. Vďaka prepojeniu bodov nemusíme vynakladať veľa úsilia na sledovanie a porovnanie trendu. Zmena v tomto kroku sa mi zdá byť ešte výraznejšia než predchádzajúca. Pri prvom grafe by väčšina používateľov strávila len minimum času a rýchlo by ho preskočila, pretože informácie neboli na prvý pohľad zaujímavé. Druhý graf už poskytol potrebný kontext – jasne vidíme rozdiely medzi dvomi radmi, ktoré by sme nemali prehliadať. Avšak, porozumenie tomuto grafu vyžaduje veľa sústredenia a môže byť únavné. Pridanie prepojenia výrazne zjednodušilo graf a umožnilo nám rýchlejšie a ľahšie pochopiť viac informácií. Mimochodom, všimli ste si, že sme odstránili jeden komponent podobnosti? Rovnaký tvar nežnížil vnímanie rozdielov. Mohli sme ho ponechať, ale všeobecne by som odporučil odstrániť každý element, ktorý sám o sebe nepridáva hodnotu.

Ako posledný aplikujeme princíp ohraničenia.

Základný graf + princíp podobnosti + princíp prepojenia + princíp ohraničenia

Keď sa na graf pozrieme teraz, zrejme nám ako prvá padne do oka výrazná červená oblasť, ktorá je v jasnom kontraste so zvyškom grafu. Typicky sa môže jednať o predpokladaný vývoj do konca roka a neohraničená oblasť bude doterajší reálny vývoj. Následne sa presúvame k vnímaniu informácií z predchádzajúcich krokov ako rozdiel v trendoch dvoch skupín.

Záver

Gestalt princípy sú mocným nástrojom pri navrhovaní vizualizácií dát, ktoré sú nielen esteticky príjemné, ale aj efektívne v komunikácii komplexných informácií. V tomto blogovom príspevku sme si prešli 6 kľúčových princípov blízkosť, podobnosť, ohraničenie, uzavretosť, plynulosť a prepojenie a ukázali sme si, ako ich aplikovať pri tvorbe vizualizácií v jazyku R. Tieto princípy nám pomáhajú usmerňovať pozornosť užívateľa, znižovať kognitívne zaťaženie a zvyšovať zrozumiteľnosť prezentovaných dát.

Pri tvorbe vizualizácií je dôležité mať na pamäti, že každý element by mal byť v návrhu zámerne umiestnený a mal by prispievať k hlavnému cieľu vizualizácie. Zbytočné prvky by mali byť eliminované, aby sa predišlo preťaženiu užívateľa informáciami. Používanie Gestalt princípov vám umožní vytvárať vizualizácie, ktoré sú nielen vizuálne príťažlivé, ale aj funkčné a efektívne v sprostredkovaní informácií.

Ak by ste sa chceli dozvedieť viac o problematike ako vizualizovať a komunikovať dáta, odporúčam knihu od Cole Nussbaumer Knaflic – Storytelling with Data, ktorá odkazuje na mnoho ďaľších zdrojov, a tiež súvisiacu stránku https://www.storytellingwithdata.com/.

Vývoj a nasadenie Shiny aplikácií v jazyku R 150 150 cleandata

Vývoj a nasadenie Shiny aplikácií v jazyku R

Shiny aplikácie umožňujú interaktívnu analýzu dát a vizualizácie v reálnom čase. Shiny, ako súčasť R ekosystému, ponúka flexibilitu a široké možnosti prispôsobenia, čo ho robí atraktívnou alternatívou k tradičným BI nástrojom. V článku jej výhody a nevýhody voči klasickým BI riešeniam, ako sú Power BI alebo Tableau. Zároveň sa pozriem na výzvy spojené s nasadením a údržbou takýchto aplikácií v produkčnom prostredí aj ukážkou reálnej aplikácie.

shiny_app

Úvod

Analyzovanie dát a vytváranie predikčných modelov sú dôležitými krokmi v rámci dátovej analýzy a data science workflow-u. Avšak, tento proces sa nekončí len analýzou samotnou. Konečným krokom je komunikovanie výsledkov. Či už ide o prezentovanie kľúčových zistení alebo o výstup v podobe dátového produktu, je nevyhnutné tieto výsledky efektívne odkomunikovať koncovým užívateľom a stakeholderom.

Existuje mnoho nástrojov, ktoré môžu byť použité na túto komunikáciu – od základných tabuliek a grafov v Exceli, cez prezentácie v PowerPointe, až po použitie pokročilejších dashboardových nástrojov ako PowerBI a Tableau. Pre špecifické potreby a väčšiu flexibilitu však môže byť nevyhnutné vytvoriť vlastné webové aplikácie, ktoré umožnia interaktívnu prácu s dátami. Jedným z nástrojov, ktorý umožňuje vytvárať takéto custom webové aplikácie, je Shiny v R (a aktuálne už aj Shiny v Pythone).

Čo je R Shiny

Shiny je framework od spoločnosti Posit (pôvodne R Studio), ktorý umožňuje vytvárať interaktívne webové aplikácie priamo v R. Je to nástroj pre R programátorov, ktorí chcú prezentovať svoje analýzy a vizualizácie interaktívnym spôsobom bez potreby vedieť HTML, CSS alebo JavaScript (hoci znalosť týchto technológií rozširuje flexibilitu, ktorú Shiny ponúka).

Shiny vs PowerBI (a iné nástroje)

Pomenujme najskôr “slona v miestnosti”. Je Shiny ten najlepší nástroj? Nie, nie je. Pre väčšinu prípadov si bohato vystačíte s Excelom a PowerBI (alebo Tableau či inými alternatívami, ale keďže mám bohaté skúsenosti s PowerBI, budem ho uvádzať ako príklad). Tieto nástroje sú nenáročné na používanie, ich „learning curve“ je ľahko zvládnuteľná na bežnej používateľskej úrovni a väčšinou sa jednoducho integrujú do spoločnosti. Poskytujú tiež dostatočnú flexibilitu, najmä MS produkty vďaka Power Query a jazyku DAX.

Prečo teda použiť Shiny? Odpoveď je jednoduchá: kedykoľvek vytvárate pokročilejšiu analytiku v R, bude jednoduchšie ju dať do produkcie natívnym nástrojom, ktorý nijakým spôsobom neobmedzuje funkcionalitu. Áno, PowerBI umožňuje použitie R a Pythonu, ale existujú obmedzenia na počet záznamov, ktoré môžete spracovať (150 000 riadkov je naozaj málo), podpora knižníc je obmedzená a vizualizácie sú statické obrázky.

Ďalším dôvodom na použitie Shiny môžu byť špecifické požiadavky na dizajn. Vďaka HTML, CSS a JavaScriptu máte prakticky neobmedzené možnosti. Rovnako máte viacero možností, kde si aplikáciu budete hostovať, čo zvyšuje flexibilitu pri nasadení v rôznych prostrediach.

Okrem toho, Shiny v kombinácii s frameworkami ako Golem alebo Rhino, poskytuje silné nástroje pre Continuous Integration/Continuous Deployment (CI/CD) vďaka integrácii s Gitom. Toto umožňuje automatizovaný a kontrolovaný proces vývoja, testovania a nasadzovania aplikácií, čo je obzvlášť užitočné v tímoch alebo pri práci na väčších projektoch. Takýto prístup zvyšuje kvalitu kódu, zrýchľuje vývoj a umožňuje rýchlejšie reagovať na zmeny a požiadavky.

Pre zosumarizovanie:

Výhody Shiny:

  • Flexibilita: Umožňuje používať celú silu R, vrátane knižníc a vlastných skriptov.
  • Open-source: Bezplatný a komunitou podporovaný nástroj.
  • Jednoduché rozšírenie: Možnosť integrácie s ďalšími nástrojmi a technológiami.
  • Výkon: Dokáže spracovať veľké množstvo dát.

Nevýhody Shiny:

  • Optimalizácia: Je nutná optimalizácia skriptov a modulov, aby užívateľ zbytočne nečakal pri dlho bežiacich výpočtoch.
  • Náročnosť: Vyžaduje znalosti R a programovania.

Výhody tradičných nástrojov:

  • Jednoduchosť použitia: Intuitívne rozhranie vhodné pre neprogramátorov.
  • Výkon: Optimalizované pre rýchle spracovanie veľkých dát.

Nevýhody tradičných nástrojov:

  • Náklady: Licenčné poplatky môžu byť vysoké.
  • Obmedzená flexibilita: Menej možností pre pokročilé analýzy a customizáciu oproti Shiny.
  • Výkon: Aj keď je PowerBI optimalizovaný pre veľké dáta, pri nesprávnej práci s ETL v Power Query a zle napísaných DAX funkciách môže výkon výrazne klesnúť, čo môže spôsobiť pomalé načítavanie a spracovanie dát.

“Vanilla” Shiny vs špecializované frameworky

Pri vývoji aplikácií v Shiny máte na výber medzi tzv. “vanilla” Shiny a špecializovanými frameworkami, ako sú Golem a Rhino. Každá možnosť má svoje výhody a nevýhody, ktoré by ste mali zvážiť v závislosti od vašich projektových potrieb.

“Vanilla” Shiny

“Vanilla” Shiny je základná verzia Shiny frameworku, ktorú väčšina používateľov začína používať. Je rýchly na nasadenie a umožňuje rýchle vytváranie prototypov a jednoduchých aplikácií. Táto verzia je ideálna pre menšie projekty alebo pre rýchle vytvorenie funkčného prototypu ako proof of concept.

Výhody:

  • Jednoduchosť a rýchlosť nasadenia.
  • Skvelé pre začínajúcich používateľov alebo menšie projekty.
  • Žiadna dodatočná záťaž z používania frameworkov, priamočiary kód.

Nevýhody:

  • Menej vhodné pre veľké a komplexné aplikácie.
  • Môže byť ťažké udržať čistý a organizovaný kód pri rozrastaní aplikácie.
  • Nedostatok robustných nástrojov na správu veľkých projektov, ako sú moduly, testovanie a CI/CD.

Golem

Golem je špecializovaný framework, navrhnutý pre vývoj robustných a produkčných Shiny aplikácií. Poskytuje silnú štruktúru pre váš projekt a podporuje modulárny prístup k vývoju, čo umožňuje lepšiu organizáciu a škálovateľnosť aplikácie. Výsledný projekt je zabalený ako R knižnica, čo prináša niekoľko výhod, vrátane jednoduchšej správy závislostí, opätovnej použiteľnosti kódu a jednoduchého nasadzovania. Benefitom je tiež kniha Engineering Production-Grade Shiny Apps od autorov Golemu.

Výhody:

  • Robustná štruktúra projektu, ktorá podporuje modularizáciu kódu.
  • Výsledok vo forme R knižnice, čo zjednodušuje správu a opätovné použitie kódu.
  • Umožňuje lepšiu správu veľkých a komplexných aplikácií.
  • Obsahuje nástroje na testovanie, nasadzovanie a CI/CD procesy.

Nevýhody:

  • Strmšia “learning curve” v porovnaní s “vanilla” Shiny.
  • Vyžaduje viac počiatočného nastavenia a organizácie.

Rhino

Rhino je moderný framework od spoločnosti Appsilon pre Shiny aplikácie, zameraný na väčšie projekty a kolaboráciu v tíme. Je postavený na princípoch moderného vývoja softvéru, vrátane automatizovaného testovania a CI/CD, čo ho robí ideálnym pre vývoj v prostrediach, kde sú požiadavky na kvalitu a škálovateľnosť vysoké. Rhino je navyše aktívne vo vývoji a pripravuje sa aj verzia pre Python, čo prináša sľubné rozšírenie možností pre používateľov preferujúcich Python.

Výhody:

  • Integrácia s modernými vývojovými nástrojmi a postupmi.
  • Flexibilná štruktúra, ktorá umožňuje pokročilú customizáciu a integráciu s front-end technológiami.
  • Silná podpora pre tímovú prácu a verziovanie kódu.
  • Aktívny vývoj, vrátane pripravovanej podpory pre Python.

Nevýhody:

  • Vyššia komplexnosť a náročnosť na vývoj v porovnaní s “vanilla” Shiny.
  • Vyžaduje znalosť moderných vývojárskych nástrojov a postupov.

Možnosti deploymentu

Po vytvorení Shiny aplikácie prichádza na rad jej nasadenie (deployment), aby bola dostupná pre koncových užívateľov. Existuje niekoľko možností, ako Shiny aplikáciu nasadiť, pričom každá z nich má svoje výhody a nevýhody.

Shinyapps.io

Najjednoduchší spôsob nasadenia je prostredníctvom shinyapps.io, ktorý je možný na pár kliknutí priamo cez RStudio IDE. Tento hostingový servis od Posit umožňuje rýchle a jednoduché nasadenie aplikácie.

Výhody:

  • Jednoduchosť nasadenia: Nasadenie aplikácie je možné vykonať na pár kliknutí priamo z RStudio.
  • Bez nutnosti infraštruktúry: Nemusíte sa starať o servery, firewall ani hardvér – všetko je spravované v cloude.
  • Free tier: Umožňuje hosťovať až 5 aplikácií zdarma, čo je výhodné pre menšie projekty alebo testovanie.

Nevýhody:

  • Výkon: Vo free verzii môže byť výkon aplikácie pomalší, čo sa prejavuje najmä pri vyššej záťaži alebo zložitých aplikáciách.
  • Zabezpečenie: Shinyapps.io ponúka základné možnosti autentifikácie, ale pokročilé zabezpečenie a kontrolu prístupu je obmedzené.
  • Zdieľaná platforma: Aplikácie bežia na zdieľanej infraštruktúre, čo môže mať vplyv na spoľahlivosť a výkon v prípade veľkého počtu používateľov.

Posit Connect

Posit Connect je profesionálna platforma pre nasadenie Shiny aplikácií a iných dátových produktov (napr. R Markdown, Plumber API, Python aplikácie), ktorá je navrhnutá pre podnikové prostredia. Poskytuje pokročilé možnosti nasadzovania, správu prístupov a monitorovanie aplikácií.

Výhody:

  • Široká podpora obsahu: Podporuje rôzne typy obsahu vrátane Shiny aplikácií, R Markdown reportov, Python skriptov a viac.
  • Bezpečnosť: Umožňuje pokročilé možnosti autentifikácie a kontroly prístupu, čím poskytuje lepšie zabezpečenie dát.
  • Škálovateľnosť: Podpora pre škálovanie aplikácií a správu veľkého počtu používateľov a prístupových práv.
  • Zjednodušené nasadenie: Možnosť nasadenia aplikácií cez push-button alebo pomocou Git.
  • Monitoring a správa: Poskytuje nástroje na sledovanie výkonu aplikácií a správu servera za účelom optimalizácie prevádzky.

Nevýhody:

  • Náklady: Posit Connect je platená služba, čo môže byť finančne náročné pre menšie tímy alebo jednotlivcov.
  • Komplexnosť: Vyžaduje infraštruktúru a určité technické znalosti pre správu a údržbu.

Docker + Cloud služby (GCP, AWS, Azure)

Pre pokročilejších používateľov je možné nasadiť Shiny aplikáciu pomocou Dockeru a cloudových služieb ako Google Cloud Platform (GCP), Amazon Web Services (AWS) alebo Microsoft Azure.

Výhody:

  • Flexibilita: Možnosť nasadiť aplikáciu na rôzne cloudové platformy podľa preferencií.
  • Škálovateľnosť: Vysoká škálovateľnosť a možnosť spravovať zdroje podľa aktuálnych potrieb.
  • Kontrola: Úplná kontrola nad infraštruktúrou a konfiguráciou prostredia.

Nevýhody:

  • Komplexnosť: Vyžaduje pokročilé technické znalosti na konfiguráciu Dockeru a cloudových služieb.
  • Náklady: Prevádzka v cloude môže byť nákladná, najmä pri nesprávnej konfigurácii zdrojov.

Docker + Lokálny RStudio Server

Nasadenie Shiny aplikácie pomocou Dockeru a lokálneho RStudio Servera je ďalšou možnosťou pre tímy, ktoré chcú mať úplnú kontrolu nad svojou infraštruktúrou.

Výhody:

  • Kontrola: Úplná kontrola nad prostredím a konfiguráciou servera.
  • Izolácia: Docker poskytuje izolované prostredie pre aplikácie, čo zlepšuje bezpečnosť a stabilitu.
  • Nákladová efektívnosť: Ak už máte existujúcu infraštruktúru, náklady môžu byť nižšie v porovnaní s cloudovými službami.

Nevýhody:

  • Komplexnosť: Vyžaduje správu a údržbu vlastnej infraštruktúry, čo môže byť náročné na čas, financie a technické zdroje.
  • Obmedzená škálovateľnosť: Lokálna infraštruktúra môže byť limitovaná dostupnými zdrojmi.

Príkladová Shiny Aplikácia

Táto príkladová Shiny aplikácia bola vytvorená pomocou frameworku Rhino a predstavuje posledný krok v rámci projektu, ktorý začal získavaním dát pomocou web scrapingu, spracovaním dát, a následne tvorbou predikčného modelu. Celý projekt bol zdokumentovaný v sérii článkov:

Aplikácia umožňuje používateľom preskúmať a vizualizovať tieto dáta. Ako hlavný benefit, ktorý demonštruje výhody použitia Shiny (okrem custom dizajnu), je integrácia predikčného modelu. Používatelia môžu zadať parametre bytu a aplikácia im poskytne odhadovanú cenu, čo je praktický príklad využitia pokročilej analytiky a interaktívnych možností Shiny.

Aplikáciu si môžete vyskúšať na shinyapps.io alebo ako kontajnerizovanú aplikáciu na Google Cloud Platform (GCP).

  • 1
  • 2