NMSA230 - Úvod do programování v R

Zimný semester 2022/2023 | Cvičenie 6 | St 14/12/22

zdrojový Rmd súbor



Program R (dostupný pod GNU GPL licenciou) je k dispozícii k stiahnutiu (free of charge) na adrese

https://www.r-project.org

K dispozícii sú distribúcie s priamou podporou pre OS Windows, Linux aj Macintosh.

Základnú inštaláciu programu R je možne jednoducho rozšíriť pomocou dodatočných knižníc (balíčkov), ktoré sú k dispozícii na rôznych online repozitároch (zoznam hlavných repozitárov je na adrese https://cran.r-project.org/mirrors.html). Jednotlivé R knižnice sú tvorené samotnými užívateľmi softwaru R a ich správne fungovanie nie je garantované - je preto namieste určitá opatrnosť a hlavne aktívne premýšľanie pri ich používaní.

Pre užívateľov programu R sú k dispozícii aj rôzne grafické rozhrania, ktoré je možne dodatočne nainštalovať a umožňujú (v určitých smeroch) jednoduchšiu a prehľadnejšiu prácu. Najznámejší a pravdepodobne aj jeden z najlepších R interfacov je RStudio.

Užitočné materiály pre prácu so štatistickým softwarom R

  • Bína, V., Komárek, A. a Komárková, L.: Jak na jazyk R. (PDF súbor)
  • Komárek, A.: Základy práce s R. (PDF súbor)
  • Kulich, M.: Stručný úvod do R. (PDF súbor)
  • Scott, T.: An Introduction to R (PDF súbor)
  • De Vries, A. a Meys, J.: R for Dummies. (ISBN-13: 978-1119055808)


Cieľom posledného semináru NMSA 230 v občianskom roku 2022 (ale nie posledný seminár vrámci akademického roka) je stručná ukážka fungovania R knižnice Shiny.

VI. Knižnica Shiny

Shiny je (open source) knižnica pre štatistický program R (inštalácia pomocou štandardného príkazu install.packages("shiny")), ktorá umožňuje vytvárať hyperaktívne webové aplikácie, pomocou ktorých dokáže koncový úžívateľ jednoducho meniť nastavenia a kontrolovať priebeh výpočtu/analýzy nejakého konkrétneho procesu (napr. štatistickej analýzy datového súboru). V tomto smere má svoje zjavné výhody aj nevýhody.

Knižnica shiny umožňuje jednoducho premeňiť R-kový zdrojový kód na interaktívnu webovú aplikáciu. Vyžaduje k tomu ale tzv. shiny server, ktorý beží na hosťovskom počítači spolu s programom R a umožňuje tak webovej aplikácii na klientskom počítači (v určitom zmysle) plnohodnotne fungovať – t.j., vyhodnocovať R-kové príkazy v závislosti na klientských modifikáciach, ktoré uskutočnuje priamo vo svojom internetovom prehliadači.

Inšpirácia a niekoľko príkladov vytvorených pomocou knižnice shiny: http://shiny.rstudio.com/gallery/

Pre účely tohto cvičenia (a pre zjavnú jednoduchosť) nebude potrebné inštalovať shiny server na hosťovskom počítači. Ako “hosťovský počítač” bude slúžiť priamo počítač/notebook na ktorom pracujete. Následujäce príklady budu využívať len lokálny pristup k programu R a “hosťovský shiny server” bude imitovaný priamo počítačom/notebookom, ktorý ma každý k dispozícii a na ktorom pracuje.

1. Spustenie Shiny aplikácie

K vytvoreniu funkčnej shiny aplikácie je potrebných niekoľko krokov:

  • nainštalovať a načítať knižnicu shiny:

    library("shiny")
  • vytvoriť (HTML) stránku pomocou R-kového príkazu fluidPage(). Táto web (html) stránka bude následne pre aplikáciu slúžiť ako priestor pre zadávanie vstupných hodnôt pre program R a zároveň bude poskytovať potrebné zdrojové informácie pre plnohodnotný výpočet – resp. štatistickúp analýzu v R.
    Pomocou tejto stránky užívateľ kontroluje aplikáciu a modifikuje výpočty/analýzu;
  • naprogramovať príslušný R-kový kód, ktorý beží na serveri shiny a ktorý pracuje so vstupnými informáciami poskytnutými webovou stránkou vytvorenou pomocou fluidPage() a po spracovaní a vyhodnotení R-kového zdrojového kódu odošle príslušný výstup späť na stránku. Požadovaný výstup sa uživateľovi zobrazí priamo na webovej stránke;
  • spustit samotnú shiny aplikáciu pomocou príkazu shinyApp();

Najjednoduchší príklad funkčnej shiny aplikácie (ktorá ale v zásade nič nerobí), je vytvorená pomocou nasledujúcej časti R-kového kódu:

library("shiny")

ui <- fluidPage("Hello Word"
   ### su za zadavaju vstupne informacie (inputs) a zobrazuju sa vystupy (outputs)
)

server <- function(input, output){
  ### R-kovy zdrojovy kod, ktory vyuziva list input (vstupne informacie) a vytvara z toho list vystupov (output)
}

### spustenie samotnej aplikacie (otvori webovy prehliadac s pozadovanou strankov vytvorenou vo fluidPage())
shinyApp(ui = ui, server = server) 

Obe vyššie vytvorené časti – t.j., webová (html) stránka ui, aj shiny server server lze následne doplniť o dodatočné informácie – vhodne štrukturovaný HTML kód, preddefinované moduly na zadávanie jednotlivých príkazov, alebo konkrétne data pre program R, na základe ktorých sa pripraví výstup – t.j., moduly na vizualizáciu výsledkov (tabuľky, obrázky, grafy a pod.).

Doležité


Pri spustení R-kového kódu uvedeného vyššie, dôjde k otvoreniu webového prehliadača, v ktorom sa otvorí prázdna stránka s uvítaním “Hello World”. Príkazový riadok v R-ku (konzola v RStudio) zostáva aktívna a nie je možné zadavať prostredníctvom konzoly dalšie príkazy. R-ko očakáva, že príkazy bude dostavať prostredníctvom otvoreného a aktivného webového prehliadača. Keďže nateraz nemáme v prehliadači nič vytvorené (príkaz fluidPage() je prázdny), musíme R-ko ukončiť manuálne, buď kliknutím na tlačítko STOP, alebo stlačením kombinácie kláves CTRL + C.



2. Jednoduché (štatistické) príklady pomocou shiny

Všetky hodnoty, ktoré potrebuje program R ako vstupné hodnoty pre správne fungovanie (resp. štatistickú analýzu), sú automaticky uložené v liste (R object list()) s názvom input a na jednotlivé zložky listu je možné sa priamo odkazovať pomocou ID nálepky použitej pri vstupe.

Analogicky aj všetky výstupy, ktoré shiny server pripraví pre následné zobrazenie prostredníctvom klientskej webovej stránky, sa ukladajú do listu (R object) s názvom output a na jednotlivé zložky sa opať môžeme priamo odkazovať pomocou príslušných ID nálepiek.

Nasledujúci príklad umožnuje vykresliť histogram pre náhodný výber z normálneho rozdelenia \(N(\mu, \sigma^2)\) o rozsahu \(n \in \mathbb{N}\), avšak všetky tri parametre (\(\mu \in \mathbb{R}\), \(\sigma^2 > 0\), aj \(n \in \mathbb{N}\)) môže užívateľ nastaviť samostatne prostredníctvom aktívneho webového prehliadača vytvoreného pomocou shiny.

Histogram a odhad hustoty sa interaktvívne vykreslí priamo v prehliadači (ako html stránka), hneď po zadaní vstupných hodnôt.

library("shiny")

ui <- fluidPage(
  
  title = "Simple Example: Simulating data from normal distribution",
  
  sidebarPanel(
    sliderInput(inputId = "mean", label = "Choose Mean Value", min = -100, max = 100, value = 0),
    sliderInput(inputId = "var", label = "Choose Variance Value", min = 0, max = 10, value = 1),
    numericInput("number", label = "Number of Observations", value = 10),
    numericInput("breaks", label = "Number of Breaks", value = 10)
  ),
  
  mainPanel(
    plotOutput(outputId = "density")
  )
)

server <- function(input, output){
  output$density <- renderPlot({sample <- rnorm(input$number, input$mean, sqrt(input$var))
                                hist(sample, breaks = input$breaks, col = "blue", freq = F)
                                lines(density(sample), col = "red", lwd = 2)
                                })
}

shinyApp(ui = ui, server = server)



Ak ste príkazy zadali správne, vo webovom prehliadači by ste mali vidieť niečo podobné:

Pomocou nástrojov na zadávanie vstupných hodnôt na ľavej strane je možné modifikovať nastavenie generátoru náhodných čísel. Následne sa v programe R vygeneruje nový/iný náhodný výber a príslušne sa prekresli histogram a odhad hustoty.

Príkazový riadok v RStudio zostáva naďalej aktívny a nie je možné zadavať príkazy jinak, než pomocou otvoreného webového prehliadača - program R totiž očakáva vstupné hodnoty, ktoré budu zadané pouze prostredníctvom nástrojov na webovej stránke. V prípade, že chceme R sekciu ukončiť, je nutné stlačiť tlačítko STOP alebo kombináciu kláves CTRL + C (prípadne zatvoriť okno webového prehliadača).

Doležité


Všimnite si, akým sposobom funguje zadávanie vstupných hodnôt a akým spôsobom sú tieto hodnoty následne predané do programu R na sever shiny
  • V knižnici shiny je niekoľko rôzných nástrojov (tzv. widgets) na zadávanie vstupných hodnôt - viď napr. https://shiny.rstudio.com/tutorial/written-tutorial/lesson3/;
  • Každý príkaz, ktorý umožnuje zadávať vstupné hodnoty, musí mať priradené jednoznačné ID - pozri prvý argument v príkazoch vyššie. S týmto ID je potom vstupná hodnota predaná v liste input do R-ka: napr. vstupná hodnota pre voľbu strednej hodnoty je uložena v input$mean;
  • Fiktívny server - v našom prípade užívateľský počítač - využíva hodnoty uložené v liste input a v sérii R-kových príkazov pripraví príslušný výstup/výstupy, ktoré analogicky uloži do listu output;
  • V druhej časti príkazu fluidPage() umiestňujeme na webovú stránku pripravené výstupy, ktoré predal server po spracovaní programom R;
  • Analogicky ako v prípade zadávania vstupných hodnôt, aj pre vykresľovanie výstupov je v knižnici shiny k dispozícii niekoľko užitočných nástrojov - viď napr. https://shiny.rstudio.com/tutorial/written-tutorial/lesson4/;



Samostatne


  • Využijte ďalšie možnosti, ktoré ponúka knižnica shiny a pokuste sa vytvorit interaktívnu aplikáciu, pomocou ktorej budete analyzovať nejaky datový súbor, ktorý je k dispozícii v programe R, avšak analýza bude závisieť na uživateľských nastaveniach (napr. výber premenných, voľba podsúboru dat, voľba hladiny spoľahlivosti a pod.).
  • Pokuste sa využiť rôzne možnosti zadávania vstupných informácii a tiež rôzne možnosti prezentovania výstupu.
  • Využijte rôzne varianty k peknému a účelnému usporiadaniu nástrojov na zadávanie vstupných informacii a panelov na vykresľovanie spočítaných výstupov.
  • Komplexnejšia ukážka s využitim viacerých panelov pre rôzne varianty výstupov je napr. nižšie:

    library("shiny")
    
    ui <- fluidPage(
      
      title = "Simple Example",
      
      sidebarPanel(
        sliderInput(inputId = "mean", label = "Choose Mean Value", min = -100, max = 100, value = 0),
        sliderInput(inputId = "var", label = "Choose Variance Value", min = 0, max = 10, value = 1),
        numericInput("number", label = "Number of Observations", value = 10),
        numericInput("breaks", label = "Number of Breaks", value = 10)
      ),
      
      mainPanel(
        tabsetPanel(
          tabPanel("Plot",  plotOutput(outputId = "density")), 
          tabPanel("Summary", verbatimTextOutput("summary")),
          tabPanel("Regression", plotOutput(outputId = "regression")),
          tabPanel("Regression Summary", verbatimTextOutput("regsum"))
        )
      )
    )
    
    server <- function(input, output){
      
      output$density <- renderPlot({set.seed(1234)
                                    data <- data.frame(1:input$number, rnorm(input$number, input$mean, sqrt(input$var)))
                                    hist(data[,2], breaks = input$breaks, col = "blue", freq = F)
                                    lines(density(data[,2]), col = "red", lwd = 2)
                                    })
      
      output$summary <- renderPrint({set.seed(1234)
                                     data <- data.frame(1:input$number, rnorm(input$number, input$mean, sqrt(input$var)))
                                     summary(data[,2])})
      
      output$regression <- renderPlot({set.seed(1234)
                                       data <- data.frame(1:input$number, rnorm(input$number, input$mean, sqrt(input$var)))
                                       plot(data[,2] ~ data[,1])
                                       model <- lm(data[,2] ~ data[,1], data = data, xlab = "Observation Number", ylab = "Observation Value")
                                       abline(model$coeff[1], model$coeff[2], col = "red", lwd = 2)})
      
      output$regsum <- renderPrint({set.seed(1234)
                                    data <- data.frame(1:input$number, rnorm(input$number, input$mean, sqrt(input$var)))
                                    plot(data[,2] ~ data[,1])
                                    model <- lm(data[,2] ~ data[,1], data = data, xlab = "Observation Number", ylab = "Observation Value")
                                    summary(model)})
    }
    
    shinyApp(ui = ui, server = server)
  • Vyskúšajte uvedený skript a pokúste sa ho podľa vlastných nápadov vhodne modifikovať. Vygenerovaná webová stránka by mala vyzerať nejak takto:




3. Rôzne (novšie) alternatívy pre shiny

Webové stránky vytvorené pomocou R knižnice shiny je možné priamo rozšíriť napr. o CSS štýly, ale JavaScrip kódy. Samozrejme exustujú aj alternatívne možnosti, najznámejšie sú asi

prípadne niektoré ďalšie, uvedené napr. na stránke https://stackshare.io/shiny/alternatives





Požiadavky na zápočet

  • Nutnou a zároveň postačujúcou podmienkou na získanie zápočtu (ak má študent/študentka predmet riadne zapísaný v aktuálnom školskom roku v systéme SIS) je vypracovanie parciálných úloh zadaných v priebehu semestra a včasné odovzdanie celkového PDF reportu vrámci stanoveného deadlinu.
  • Parciálne úlohy postupne zadávané na seminároch č.1 až 4 zahrňovali vygenerovanie vlastného datového súboru, vytvorenie niektorých dôležitých popisných charakteristík s vhodným grafickým doplnením a celkové spracovanie pomocou R knižnice ‘Sweave’.
  • Finálný súbor PDF je potrebné zaslať emailom

    na adresu maciak[AT]karlin.mff.cuni.cz najneskôr do konca skúškového obdobia, t.j. do 12.02.2023..